diff --git a/wallet/entrypoints/background.ts b/wallet/entrypoints/background.ts index a12ffae..ee3ea6b 100644 --- a/wallet/entrypoints/background.ts +++ b/wallet/entrypoints/background.ts @@ -12,7 +12,7 @@ import { createPublicClient, http, parseEther, formatEther, type TypedDataDefinition } from "viem"; import { Keyring } from "../src/keyring/keyring"; import { parseTypedData } from "../src/provider/typed-data"; -import { WorkerOperator, NETWORKS, type MinimalPublicClient } from "lightnode-sdk"; +import { readWorkerStatus } from "../src/rpc/worker"; import { encryptVault, decryptVault, type EncryptedVault } from "../src/keyring/vault"; import { chainById, lightchainMainnet } from "../src/rpc/chains"; import { type BgMessage, type WalletOp, type JsonRpcRequest, RpcError } from "../src/provider/protocol"; @@ -98,23 +98,10 @@ async function handleWalletOp(op: WalletOp): Promise { const wei = await publicClient().getBalance({ address: op.address as `0x${string}` }); return { wei: wei.toString(), lcai: formatEther(wei) }; } - case "workerStatus": { - // Read-only worker registry/stake lookup via the SDK. No key needed; we - // return only number/bool fields (chrome.runtime can't structured-clone bigint). - const wo = new WorkerOperator(NETWORKS.mainnet, { - publicClient: publicClient() as unknown as MinimalPublicClient, - workerAddress: op.address as `0x${string}`, - }); - const s = await wo.status(); - return { - registered: s.registered, - belowFloor: s.belowFloor, - stakeLcai: s.stakeLcai, - minStakeLcai: Number(s.minStakeWei) / 1e18, - headroomLcai: s.headroomLcai, - claimableLcai: s.claimableLcai, - }; - } + case "workerStatus": + // Read-only registry/stake lookup (no key). Already returns number/bool + // fields only, so it survives chrome.runtime's structured clone (no bigint). + return readWorkerStatus(publicClient(), op.address as `0x${string}`); case "send": { const kr = await restore(); const acct = kr?.accountFor(op.from); diff --git a/wallet/entrypoints/popup/wallet-api.ts b/wallet/entrypoints/popup/wallet-api.ts index 7d05bd2..c77eafd 100644 --- a/wallet/entrypoints/popup/wallet-api.ts +++ b/wallet/entrypoints/popup/wallet-api.ts @@ -19,11 +19,4 @@ export interface PendingRequest { origin: string; params?: unknown[]; } -export interface WorkerStatusView { - registered: boolean; - belowFloor: boolean; - stakeLcai: number; - minStakeLcai: number; - headroomLcai: number; - claimableLcai: number; -} +export type { WorkerStatusView } from "../../src/rpc/worker"; diff --git a/wallet/package-lock.json b/wallet/package-lock.json index 5c8359c..596907e 100644 --- a/wallet/package-lock.json +++ b/wallet/package-lock.json @@ -12,7 +12,6 @@ "@noble/hashes": "^1.6.1", "@scure/bip32": "^1.6.2", "@scure/bip39": "^1.5.4", - "lightnode-sdk": "file:../sdk", "react": "^18.3.1", "react-dom": "^18.3.1", "viem": "^2.21.0" @@ -30,6 +29,7 @@ "../sdk": { "name": "lightnode-sdk", "version": "0.18.3", + "extraneous": true, "license": "MIT", "dependencies": { "@noble/ciphers": "^1.0.0", @@ -4519,10 +4519,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/lightnode-sdk": { - "resolved": "../sdk", - "link": true - }, "node_modules/lines-and-columns": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-2.0.4.tgz", diff --git a/wallet/package.json b/wallet/package.json index c4cc170..ee9daba 100644 --- a/wallet/package.json +++ b/wallet/package.json @@ -5,10 +5,7 @@ "type": "module", "description": "Self-custodial EOA browser wallet for LightChain. Non-custodial: keys never leave the device. Not an official LightChain package.", "scripts": { - "build:sdk": "npm --prefix ../sdk install --no-audit --no-fund && npm --prefix ../sdk run build", - "predev": "npm run build:sdk", "dev": "wxt", - "prebuild": "npm run build:sdk", "build": "wxt build", "zip": "wxt zip", "compile": "tsc --noEmit", @@ -19,7 +16,6 @@ "@noble/hashes": "^1.6.1", "@scure/bip32": "^1.6.2", "@scure/bip39": "^1.5.4", - "lightnode-sdk": "file:../sdk", "react": "^18.3.1", "react-dom": "^18.3.1", "viem": "^2.21.0" diff --git a/wallet/src/rpc/worker.ts b/wallet/src/rpc/worker.ts new file mode 100644 index 0000000..980c9f9 --- /dev/null +++ b/wallet/src/rpc/worker.ts @@ -0,0 +1,48 @@ +/** + * Worker-status reads, inlined with viem so the wallet has ZERO build-time + * dependency on the lightnode-sdk monorepo package (which needs the repo's + * hoisted @types/node to compile). Same 4 calls the SDK's WorkerOperator.status() + * makes, against the LightChain mainnet worker contracts. + */ +import { type PublicClient, parseAbi } from "viem"; + +// LightChain mainnet: WorkerRegistry is a genesis predeploy; AIConfig + JobRegistry are proxies. +const WORKER_REGISTRY = "0x0000000000000000000000000000000000001002" as const; +const AI_CONFIG = "0x24D11533C354092ed6E18b964257819cE78Ce77D" as const; +const JOB_REGISTRY = "0xfB15F90298e4CcD7106E76fFB5e520315cC42B0b" as const; + +const REGISTRY_ABI = parseAbi([ + "function isWorkerRegistered(address) view returns (bool)", + "function getWorkerStake(address) view returns (uint256)", +]); +const AI_CONFIG_ABI = parseAbi(["function getMinWorkerStake() view returns (uint256)"]); +const JOB_REGISTRY_ABI = parseAbi(["function workerBalance(address) view returns (uint256)"]); + +export interface WorkerStatusView { + registered: boolean; + belowFloor: boolean; + stakeLcai: number; + minStakeLcai: number; + headroomLcai: number; + claimableLcai: number; +} + +const toLcai = (wei: bigint) => Number(wei) / 1e18; + +export async function readWorkerStatus(client: PublicClient, address: `0x${string}`): Promise { + // minStake comes from AIConfig (canonical on both networks), not the registry getter. + const [registered, stakeWei, minStakeWei, claimableWei] = await Promise.all([ + client.readContract({ address: WORKER_REGISTRY, abi: REGISTRY_ABI, functionName: "isWorkerRegistered", args: [address] }), + client.readContract({ address: WORKER_REGISTRY, abi: REGISTRY_ABI, functionName: "getWorkerStake", args: [address] }), + client.readContract({ address: AI_CONFIG, abi: AI_CONFIG_ABI, functionName: "getMinWorkerStake" }), + client.readContract({ address: JOB_REGISTRY, abi: JOB_REGISTRY_ABI, functionName: "workerBalance", args: [address] }), + ]); + return { + registered, + belowFloor: registered && stakeWei < minStakeWei, + stakeLcai: toLcai(stakeWei), + minStakeLcai: toLcai(minStakeWei), + headroomLcai: toLcai(stakeWei - minStakeWei), + claimableLcai: toLcai(claimableWei), + }; +}