{"version":3,"file":"delegate-signer.mjs","names":["realAuthPost","body"],"sources":["../../../src/services/auth/delegate-signer.ts"],"sourcesContent":["import { isPrivateKey, Near, type PrivateKey } from \"near-kit\";\nimport type { NetworkId } from \"../registry/fastkv\";\nimport { openInBrowser, startDeviceLogin } from \"./device-login\";\nimport { generateNearKeyPair } from \"./near-cli\";\nimport { type DelegateKeyRecord, readSessionHandle, updateSessionHandle } from \"./session\";\nimport { authPost as realAuthPost, type SiteClientShape } from \"./site-client\";\n\nconst realSiteClient = { authPost: realAuthPost } as Pick<SiteClientShape, \"authPost\">;\n\nexport interface RelayResult {\n  success: true;\n  txHash?: string;\n}\n\nexport interface DelegateSubmitOptions {\n  account: string;\n  contract: string;\n  network: NetworkId;\n  args: Record<string, string>;\n  delegatePrivateKey: string;\n  relayEndpoint: string;\n  apiKey: string;\n  gas?: string;\n}\n\nfunction relayErrorMessage(message: string): string {\n  return message.replace(/\\n/g, \" \");\n}\n\nexport async function submitRegistryWriteDelegated(\n  opts: DelegateSubmitOptions,\n  siteClient: Pick<SiteClientShape, \"authPost\"> = realSiteClient,\n): Promise<RelayResult> {\n  const near = new Near({\n    network: opts.network,\n    defaultSignerId: opts.account,\n    privateKey: assertPrivateKey(opts.delegatePrivateKey),\n  });\n\n  const delegate = await near\n    .transaction(opts.account)\n    .functionCall(opts.contract, \"__fastdata_kv\", opts.args, {\n      gas: \"300 Tgas\",\n      attachedDeposit: \"0 yocto\",\n    })\n    .delegate({ receiverId: opts.contract, blockHeightOffset: 200 });\n\n  const { status, json } = await siteClient.authPost(\n    opts.relayEndpoint.replace(/\\/api\\/auth\\/near\\/relay$/, \"\"),\n    \"/near/relay\",\n    { payload: delegate.payload },\n    undefined,\n    { \"x-api-key\": opts.apiKey },\n  );\n\n  if (status >= 400) {\n    let detail = `Relay rejected the transaction (HTTP ${status})`;\n    const relayMessage =\n      typeof (json as { message?: string }).message === \"string\"\n        ? (json as { message: string }).message\n        : typeof (json as { error?: string }).error === \"string\"\n          ? (json as { error: string }).error\n          : undefined;\n    if (relayMessage) {\n      detail = `${detail}: ${relayErrorMessage(relayMessage)}`;\n    }\n    throw new Error(detail);\n  }\n\n  const body = json as { txHash?: string };\n  return { success: true, txHash: body.txHash };\n}\n\nfunction assertPrivateKey(key: string): PrivateKey {\n  if (!isPrivateKey(key)) {\n    throw new Error(\"Invalid delegate key format (expected ed25519:…)\");\n  }\n  return key as PrivateKey;\n}\n\nexport interface EnsureDelegateKeyOptions {\n  configDir: string;\n  account: string;\n  contract: string;\n  network: NetworkId;\n  siteUrl: string;\n}\n\nexport async function ensureDelegateKey(\n  opts: EnsureDelegateKeyOptions,\n): Promise<DelegateKeyRecord> {\n  const existing = readSessionHandle(opts.configDir)?.delegateKey;\n  if (\n    existing &&\n    existing.accountId === opts.account &&\n    existing.contract === opts.contract &&\n    existing.network === opts.network\n  ) {\n    return existing;\n  }\n\n  const keyPair = generateNearKeyPair();\n\n  const login = await startDeviceLogin({\n    siteUrl: opts.siteUrl,\n    delegate: {\n      pubKey: keyPair.publicKey,\n      contract: opts.contract,\n      network: opts.network,\n    },\n    account: opts.account,\n  });\n\n  console.log(`  One-time code: ${login.userCode}`);\n  await openInBrowser(login.verificationUrl).catch((error: unknown) => {\n    console.log(`  ⚠ ${(error as Error).message}`);\n  });\n  console.log(`  Waiting for delegate-key approval at ${login.verificationUrl}…`);\n\n  await login.waitForApproval();\n\n  const record: DelegateKeyRecord = {\n    publicKey: keyPair.publicKey,\n    privateKey: keyPair.privateKey,\n    accountId: opts.account,\n    network: opts.network,\n    contract: opts.contract,\n    mintedAt: new Date().toISOString(),\n  };\n  updateSessionHandle(opts.configDir, (current) => ({ ...current, delegateKey: record }));\n  return record;\n}\n"],"mappings":";;;;;;;AAOA,MAAM,iBAAiB,EAAYA,SAAa;AAkBhD,SAAS,kBAAkB,SAAyB;CAClD,OAAO,QAAQ,QAAQ,OAAO,GAAG;AACnC;AAEA,eAAsB,6BACpB,MACA,aAAgD,gBAC1B;CAOtB,MAAM,WAAW,MAAM,IANN,KAAK;EACpB,SAAS,KAAK;EACd,iBAAiB,KAAK;EACtB,YAAY,iBAAiB,KAAK,kBAAkB;CACtD,CAE0B,CAAC,CACxB,YAAY,KAAK,OAAO,CAAC,CACzB,aAAa,KAAK,UAAU,iBAAiB,KAAK,MAAM;EACvD,KAAK;EACL,iBAAiB;CACnB,CAAC,CAAC,CACD,SAAS;EAAE,YAAY,KAAK;EAAU,mBAAmB;CAAI,CAAC;CAEjE,MAAM,EAAE,QAAQ,SAAS,MAAM,WAAW,SACxC,KAAK,cAAc,QAAQ,6BAA6B,EAAE,GAC1D,eACA,EAAE,SAAS,SAAS,QAAQ,GAC5B,QACA,EAAE,aAAa,KAAK,OAAO,CAC7B;CAEA,IAAI,UAAU,KAAK;EACjB,IAAI,SAAS,wCAAwC,OAAO;EAC5D,MAAM,eACJ,OAAQ,KAA8B,YAAY,WAC7C,KAA6B,UAC9B,OAAQ,KAA4B,UAAU,WAC3C,KAA2B,QAC5B;EACR,IAAI,cACF,SAAS,GAAG,OAAO,IAAI,kBAAkB,YAAY;EAEvD,MAAM,IAAI,MAAM,MAAM;CACxB;CAGA,OAAO;EAAE,SAAS;EAAM,QAAQC,KAAK;CAAO;AAC9C;AAEA,SAAS,iBAAiB,KAAyB;CACjD,IAAI,CAAC,aAAa,GAAG,GACnB,MAAM,IAAI,MAAM,kDAAkD;CAEpE,OAAO;AACT;AAUA,eAAsB,kBACpB,MAC4B;CAC5B,MAAM,WAAW,kBAAkB,KAAK,SAAS,CAAC,EAAE;CACpD,IACE,YACA,SAAS,cAAc,KAAK,WAC5B,SAAS,aAAa,KAAK,YAC3B,SAAS,YAAY,KAAK,SAE1B,OAAO;CAGT,MAAM,UAAU,oBAAoB;CAEpC,MAAM,QAAQ,MAAM,iBAAiB;EACnC,SAAS,KAAK;EACd,UAAU;GACR,QAAQ,QAAQ;GAChB,UAAU,KAAK;GACf,SAAS,KAAK;EAChB;EACA,SAAS,KAAK;CAChB,CAAC;CAED,QAAQ,IAAI,oBAAoB,MAAM,UAAU;CAChD,MAAM,cAAc,MAAM,eAAe,CAAC,CAAC,OAAO,UAAmB;EACnE,QAAQ,IAAI,OAAQ,MAAgB,SAAS;CAC/C,CAAC;CACD,QAAQ,IAAI,0CAA0C,MAAM,gBAAgB,EAAE;CAE9E,MAAM,MAAM,gBAAgB;CAE5B,MAAM,SAA4B;EAChC,WAAW,QAAQ;EACnB,YAAY,QAAQ;EACpB,WAAW,KAAK;EAChB,SAAS,KAAK;EACd,UAAU,KAAK;EACf,2BAAU,IAAI,KAAK,EAAC,CAAC,YAAY;CACnC;CACA,oBAAoB,KAAK,YAAY,aAAa;EAAE,GAAG;EAAS,aAAa;CAAO,EAAE;CACtF,OAAO;AACT"}