import { Account, JsonRpcProvider, KeyPair, teraToGas } from 'near-api-js'; import { postJson } from '../../lib/http.mjs'; export function createVerifierClient({ nearRpcUrl, verifierContract, accountId = '', signerPrivateKey = '', }) { const provider = new JsonRpcProvider({ url: nearRpcUrl }); const signer = signerPrivateKey ? KeyPair.fromString(signerPrivateKey) : null; const operatorAccount = accountId && signerPrivateKey ? new Account(accountId, provider, signerPrivateKey) : null; return { async currentSalt() { return callView(provider, verifierContract, 'current_salt', {}); }, async mtBatchBalanceOf({ accountId, tokenIds }) { const result = await callView(provider, verifierContract, 'mt_batch_balance_of', { account_id: accountId, token_ids: tokenIds, }); if (!Array.isArray(result)) { throw new Error('Unexpected mt_batch_balance_of response'); } return Object.fromEntries(tokenIds.map((tokenId, index) => [tokenId, String(result[index] || '0')])); }, async isPublicKeyRegistered({ accountId }) { if (!signer) return false; const publicKey = signer.getPublicKey().toString(); const result = await callView(provider, verifierContract, 'has_public_key', { account_id: accountId, public_key: publicKey, }).catch(() => null); if (typeof result === 'boolean') return result; return null; }, async ftWithdrawRaw({ token, receiverId, amount, memo = null, msg = null, storageDeposit = null, }) { if (!operatorAccount) throw new Error('operator account is not configured'); return operatorAccount.callFunctionRaw({ contractId: verifierContract, methodName: 'ft_withdraw', args: compact({ token, receiver_id: receiverId, amount: String(amount), memo, msg, storage_deposit: storageDeposit, }), gas: teraToGas('100'), deposit: 1n, }); }, getSigner() { return signer; }, }; } export function createSolverRelayRpcClient({ rpcUrl }) { let id = 1; return { async getStatus(intentHash) { const response = await postJson(rpcUrl, { jsonrpc: '2.0', id: id++, method: 'get_status', params: [{ intent_hash: intentHash }], }); if (response.error) { throw new Error(response.error.message || 'Solver Relay get_status failed'); } return response.result; }, }; } async function callView(provider, accountId, methodName, args) { const response = await provider.query({ request_type: 'call_function', finality: 'final', account_id: accountId, method_name: methodName, args_base64: Buffer.from(JSON.stringify(args)).toString('base64'), }); const bytes = response.result || []; const text = Buffer.from(bytes).toString('utf8'); return text ? JSON.parse(text) : null; } function compact(record) { return Object.fromEntries( Object.entries(record).filter(([, value]) => value != null), ); }