@idos-network/kwil-infra 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["KwilSigner","KwilSigner","KwilSigner","KwilSigner"],"sources":["../src/wait-for-kwil-tx.ts","../src/create-kwil-client.ts","../src/mm-token/create-mm-token-kwil-signer.ts","../src/create-kgw-authenticated-fetch.ts","../src/near/get-config.ts","../src/near/create-near-wallet-kwil-signer.ts","../src/xrp/signer.ts","../src/create-kwil-signer.ts"],"sourcesContent":["const KWIL_TX_POLL_DEADLINE_MS = 90_000;\nconst INITIAL_POLL_INTERVAL_MS = 300;\nconst POLL_BACKOFF_FACTOR = 1.5;\nconst MAX_POLL_INTERVAL_MS = 2_000;\nconst MAX_POLL_JITTER_MS = 100;\n\nexport type KwilTxInfo = {\n height: number;\n tx_result: {\n code: number;\n log: string;\n };\n};\n\nexport class KwilTxFailedError extends Error {\n readonly name = \"KwilTxFailedError\";\n\n constructor(\n readonly txHash: string,\n readonly code: number,\n readonly log: string,\n readonly height: number,\n ) {\n super(`Kwil transaction ${txHash} failed at height ${height} (code ${code}): ${log}`);\n }\n}\n\nexport class KwilTxPollTimeoutError extends Error {\n readonly name = \"KwilTxPollTimeoutError\";\n\n constructor(\n readonly txHash: string,\n readonly deadlineMs: number,\n options?: { cause?: unknown },\n ) {\n const lastError =\n options?.cause instanceof Error\n ? options.cause.message\n : options?.cause != null\n ? String(options.cause)\n : undefined;\n super(\n lastError\n ? `Timed out after ${deadlineMs}ms waiting for Kwil transaction ${txHash}: last error: ${lastError}`\n : `Timed out after ${deadlineMs}ms waiting for Kwil transaction ${txHash}`,\n options?.cause !== undefined ? { cause: options.cause } : undefined,\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction nextPollIntervalMs(currentIntervalMs: number): number {\n return Math.min(currentIntervalMs * POLL_BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n}\n\nfunction pollIntervalWithJitter(intervalMs: number): number {\n return intervalMs + Math.floor(Math.random() * (MAX_POLL_JITTER_MS + 1));\n}\n\nfunction isTxFinalized(txInfo: KwilTxInfo): boolean {\n return txInfo.height > 0;\n}\n\nexport async function waitForKwilTx(\n txInfo: (txHash: string) => Promise<{ data?: KwilTxInfo }>,\n txHash: string,\n deadlineMs: number = KWIL_TX_POLL_DEADLINE_MS,\n): Promise<void> {\n const deadlineAt = Date.now() + deadlineMs;\n let intervalMs = INITIAL_POLL_INTERVAL_MS;\n let lastPollError: unknown;\n\n while (Date.now() < deadlineAt) {\n let data: KwilTxInfo | undefined;\n\n // Transient poll failures (e.g. \"not found\" before the node indexes the tx) are\n // recorded and retried. Terminal tx failures are decided below, outside this catch.\n try {\n data = (await txInfo(txHash)).data;\n } catch (error) {\n lastPollError = error;\n }\n\n // height > 0 means the tx was included. Then code 0 is success; anything else is final failure.\n if (data && isTxFinalized(data)) {\n if (data.tx_result.code !== 0) {\n throw new KwilTxFailedError(txHash, data.tx_result.code, data.tx_result.log, data.height);\n }\n return;\n }\n\n // Not finalized yet (or last poll errored) — back off and try again until the deadline.\n const waitMs = pollIntervalWithJitter(intervalMs);\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n break;\n }\n\n await sleep(Math.min(waitMs, remainingMs));\n intervalMs = nextPollIntervalMs(intervalMs);\n }\n\n throw new KwilTxPollTimeoutError(\n txHash,\n deadlineMs,\n lastPollError !== undefined ? { cause: lastPollError } : undefined,\n );\n}\n","import type { ActionBody, CallBody, PositionalParams } from \"@idos-network/kwil-js/action\";\nimport type { Config } from \"@idos-network/kwil-js/config\";\nimport type { DataInfo } from \"@idos-network/kwil-js/database\";\n\nimport { type KwilSigner, NodeKwil, WebKwil } from \"@idos-network/kwil-js\";\nimport invariant from \"tiny-invariant\";\n\nimport type { ActionSchemaElement } from \"./actions\";\n\nimport { actionSchema } from \"./actions\";\nimport { waitForKwilTx } from \"./wait-for-kwil-tx\";\n\nexport { KwilTxFailedError, KwilTxPollTimeoutError } from \"./wait-for-kwil-tx\";\n\ntype CreateKwilClientParams = {\n chainId?: string;\n nodeUrl: string;\n};\n\ntype KwilActions = typeof actionSchema;\ntype ActionName = keyof KwilActions;\n\ntype AllKwilCallAction = {\n [Name in ActionName]: {\n name: Name;\n // oxlint-disable-next-line typescript/no-explicit-any -- This is fine\n inputs: Record<KwilActions[Name][number][\"name\"], any>;\n };\n};\n\ntype KwilCallActionRequestParams = AllKwilCallAction[ActionName];\n\ntype AllKwilExecuteAction = {\n [Name in ActionName]: AllKwilCallAction[Name] & { description: string };\n};\n\ntype KwilExecuteActionRequestParams = AllKwilExecuteAction[ActionName];\n\n/**\n * A client for interacting with kwil with type-safe abstractions for `call` and `execute`.\n * Has utility methods for creating actions and setting a signer.\n */\nexport class KwilActionClient {\n signer?: KwilSigner;\n readonly client: NodeKwil | WebKwil;\n\n constructor(client: NodeKwil | WebKwil) {\n this.client = client;\n }\n\n #createActionInputs(actionName: string, params: Record<string, unknown> = {}): PositionalParams {\n if (!params || !Object.keys(params).length) return [];\n\n const args = (actionSchema as Record<string, readonly ActionSchemaElement[]>)[actionName];\n\n return args.map(({ name }) => {\n const value = params[name];\n // Handle falsy values appropriately\n if (value === \"\" || value === 0) return value;\n return value ?? null;\n }) as PositionalParams;\n }\n\n #actionTypes(actionName: string): DataInfo[] {\n const args = actionSchema[actionName];\n return args.map((arg) => arg.type);\n }\n\n /**\n * Calls an action on the kwil nodes. This similar to `GET` like request.\n */\n async call<T = unknown>(\n params: KwilCallActionRequestParams,\n signer: KwilSigner | undefined = this.signer,\n ): Promise<T> {\n const action: CallBody = {\n name: params.name,\n namespace: \"main\",\n inputs: this.#createActionInputs(params.name, params.inputs),\n types: this.#actionTypes(params.name),\n };\n\n const response = await this.client.call(action as CallBody, signer);\n return response?.data?.result as T;\n }\n\n /**\n * Executes an action on the kwil nodes. This similar to `POST` like request.\n *\n * When `synchronous` is true (default), the tx is broadcast without blocking the node,\n * then confirmed by polling `txInfo` with exponential backoff.\n */\n async execute(\n params: KwilExecuteActionRequestParams,\n signer: KwilSigner | undefined = this.signer,\n synchronous = true,\n ): Promise<string> {\n invariant(signer, \"Signer is not set, you must set it before executing an action\");\n const action: ActionBody = {\n name: params.name,\n namespace: \"main\",\n description: params.description,\n inputs: [this.#createActionInputs(params.name, params.inputs)],\n types: this.#actionTypes(params.name),\n };\n const response = await this.client.execute(action, signer, false);\n const txHash = response.data?.tx_hash;\n\n if (!txHash) {\n throw new Error(`Kwil execute \"${params.name}\" did not return a transaction hash`);\n }\n\n if (synchronous) {\n await this.waitForTx(txHash);\n }\n\n return txHash;\n }\n\n /**\n * Polls the node until a broadcast transaction is mined, or throws\n * `KwilTxFailedError` / `KwilTxPollTimeoutError`.\n *\n * Called through `this` rather than directly so that it is a seam an\n * instrumentation can wrap — the wait dominates the latency of `execute`.\n */\n async waitForTx(txHash: string): Promise<void> {\n await waitForKwilTx((hash) => this.client.txInfo(hash), txHash);\n }\n\n setSigner(signer: KwilSigner | undefined): void {\n this.signer = signer;\n }\n\n /**\n * Creates action inputs from the given parameters that are used in the action body.\n */\n}\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst createKwilClient =\n (Cls: new (opts: Config) => NodeKwil | WebKwil) =>\n async ({ nodeUrl: kwilProvider, chainId }: CreateKwilClientParams): Promise<KwilActionClient> => {\n const _kwil = new Cls({ kwilProvider, chainId: \"\" });\n // oxlint-disable-next-line no-param-reassign -- Default value fallback\n chainId ||= (await _kwil.chainInfo({ disableWarning: true })).data?.chain_id;\n invariant(chainId, \"Can't discover `chainId`. You must pass it explicitly.\");\n\n const client = new KwilActionClient(\n new Cls({ kwilProvider, chainId, timeout: DEFAULT_TIMEOUT }),\n );\n\n return client;\n };\n\n/**\n * Create a kwil client for node.js environment\n */\nexport const createNodeKwilClient: (params: CreateKwilClientParams) => Promise<KwilActionClient> =\n createKwilClient(NodeKwil);\n\n/**\n * Create a kwil client for browser environment\n */\nexport const createWebKwilClient: (params: CreateKwilClientParams) => Promise<KwilActionClient> =\n createKwilClient(WebKwil);\n","import { KwilSigner } from \"@idos-network/kwil-js\";\nimport { createUkycContentUri } from \"@idos-network/utils/blob-gateway\";\nimport {\n base64UrlDecode,\n base64UrlEncode,\n utf8Decode,\n utf8Encode,\n} from \"@idos-network/utils/codecs\";\n\nconst ED25519_PUBLIC_KEY_BYTES = 32;\nconst ED25519_SIGNATURE_BYTES = 64;\n\n/** Decoded UKYC capability envelope. KGW signature data is base64url(JSON of this). */\nexport interface MmTokenEnvelope {\n payload: MmTokenPayload | Record<string, unknown>;\n signature: string;\n}\n\nexport interface MmTokenPayload {\n signing_public_key: string;\n storage_id?: string;\n [key: string]: unknown;\n}\n\n/**\n * One MM/UKYC capability, valid both as a KGW `mm_token` signer and as the\n * `Authorization: AccessToken …` credential for UKYC blob requests.\n */\nexport type MmTokenAuth = KwilSigner & {\n readonly mmTokenPayload: MmTokenPayload | Record<string, unknown>;\n /** Exact encoded envelope KGW and UKYC storage verify. Non-enumerable, so it stays out of logs. */\n readonly accessToken: string;\n /**\n * A capability signs its own envelope, never an arbitrary message. Declared so callers\n * handling a `Wallet` union can keep asking wallets for a message signature.\n */\n readonly signMessage?: undefined;\n};\n\nexport function isMmTokenAuth(value: unknown): value is MmTokenAuth {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"signatureType\" in value &&\n value.signatureType === \"mm_token\" &&\n \"identifier\" in value &&\n \"signer\" in value &&\n typeof (value as Partial<MmTokenAuth>).accessToken === \"string\"\n );\n}\n\n/** `storage_id` from the capability token used to construct this signer. */\nexport function mmTokenStorageId(signer: KwilSigner): string {\n const storageId = (signer as Partial<MmTokenAuth>).mmTokenPayload?.storage_id;\n if (typeof storageId !== \"string\" || !storageId.trim()) {\n throw new Error(\"mm_token payload is missing storage_id\");\n }\n return storageId.trim();\n}\n\nexport function mmTokenCredentialContentUri(signer: KwilSigner, credentialId: string): string {\n return createUkycContentUri(mmTokenStorageId(signer), credentialId);\n}\n\nfunction isMmTokenEnvelope(value: unknown): value is MmTokenEnvelope {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"payload\" in value &&\n value.payload !== null &&\n typeof value.payload === \"object\" &&\n !Array.isArray(value.payload) &&\n \"signature\" in value &&\n typeof value.signature === \"string\"\n );\n}\n\nfunction parseJson<T>(bytes: Uint8Array, errorMessage: string): T {\n try {\n return JSON.parse(utf8Decode(bytes)) as T;\n } catch (error) {\n throw new Error(errorMessage, { cause: error });\n }\n}\n\nfunction decodeBase64Url(value: string, errorMessage: string): Uint8Array {\n try {\n return base64UrlDecode(value);\n } catch (error) {\n throw new Error(errorMessage, { cause: error });\n }\n}\n\n/**\n * Build the MM authentication object for one UKYC capability.\n *\n * Pass the MetaMask-issued capability token as a **base64url-encoded** envelope string\n * (what KGW verifies). A decoded `{ payload, signature }` object is also accepted and\n * will be re-encoded.\n *\n * `signMessage` always returns the UTF-8 bytes of that encoded string — KGW ignores the\n * request message and only verifies the envelope.\n */\nexport function createMmTokenAuth(encodedEnvelope: string | MmTokenEnvelope): MmTokenAuth {\n let encodedToken: string;\n let envelope: MmTokenEnvelope;\n\n if (typeof encodedEnvelope === \"string\") {\n const trimmed = encodedEnvelope.trim();\n if (!trimmed) {\n throw new Error(\"Invalid mm_token envelope: empty\");\n }\n encodedToken = trimmed;\n const envelopeBytes = decodeBase64Url(trimmed, \"Invalid mm_token envelope encoding\");\n const parsed = parseJson<unknown>(envelopeBytes, \"Invalid mm_token envelope JSON\");\n if (!isMmTokenEnvelope(parsed)) {\n throw new Error(\"Invalid mm_token envelope: expected payload object and signature string\");\n }\n envelope = parsed;\n } else {\n if (!isMmTokenEnvelope(encodedEnvelope)) {\n throw new Error(\"Invalid mm_token envelope: expected payload object and signature string\");\n }\n envelope = encodedEnvelope;\n encodedToken = base64UrlEncode(utf8Encode(JSON.stringify(envelope)));\n }\n\n // KGW Verify receives UTF-8 of the base64url string, not the decoded JSON bytes.\n const signatureData = utf8Encode(encodedToken);\n\n const tokenSignatureBytes = decodeBase64Url(\n envelope.signature,\n \"Invalid mm_token envelope signature encoding\",\n );\n if (tokenSignatureBytes.length !== ED25519_SIGNATURE_BYTES) {\n throw new Error(\n `Invalid mm_token signature length: expected ${ED25519_SIGNATURE_BYTES}, got ${tokenSignatureBytes.length}`,\n );\n }\n\n const signingPublicKey = envelope.payload.signing_public_key;\n if (typeof signingPublicKey !== \"string\") {\n throw new Error(\"Invalid mm_token payload: missing signing_public_key\");\n }\n\n const signingPublicKeyBytes = decodeBase64Url(\n signingPublicKey,\n \"Invalid mm_token signing_public_key encoding\",\n );\n\n if (signingPublicKeyBytes.length !== ED25519_PUBLIC_KEY_BYTES) {\n throw new Error(\n `Invalid mm_token signing_public_key length: expected ${ED25519_PUBLIC_KEY_BYTES}, got ${signingPublicKeyBytes.length}`,\n );\n }\n\n const auth = Object.assign(\n new KwilSigner(async () => signatureData.slice(), signingPublicKeyBytes, \"mm_token\"),\n { mmTokenPayload: envelope.payload },\n );\n\n return Object.defineProperty(auth, \"accessToken\", {\n value: encodedToken,\n enumerable: false,\n }) as MmTokenAuth;\n}\n","import { type KwilSigner, NodeKwil } from \"@idos-network/kwil-js\";\nimport { BlobGateway, type BlobGatewayParams } from \"@idos-network/utils/blob-gateway\";\n\nimport type { KwilActionClient } from \"./create-kwil-client\";\nimport type { MmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nimport { isMmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nconst KGW_AUTH_ERROR_CODE = -901;\n\n/** Return true when the response means KGW auth is missing/expired.\n * May read the body only for `application/json` responses (those are probed via a clone). */\nexport type KgwAuthFailurePredicate = (response: Response) => Promise<boolean> | boolean;\n\nexport type CreateKgwAuthenticatedFetchParams = {\n kwilClient: KwilActionClient;\n signer: KwilSigner;\n fetchFn?: typeof fetch;\n isAuthFailure?: KgwAuthFailurePredicate;\n};\n\nexport type CreateKgwAuthenticatedBlobGatewayParams = CreateKgwAuthenticatedFetchParams & {\n url: string;\n maxFetchBytes?: BlobGatewayParams[\"maxFetchBytes\"];\n /**\n * UKYC storage authority for blob requests. Defaults to `signer` when that signer\n * is itself an MM authentication object, so the capability is never passed twice.\n */\n mmAuth?: MmTokenAuth;\n};\n\ntype KgwSessionNodeKwil = NodeKwil & {\n authenticateKGWAndSetCookie(signer: KwilSigner): Promise<string>;\n getKgwCookie(): string | undefined;\n};\n\nexport function createKgwAuthenticatedBlobGateway({\n url,\n maxFetchBytes,\n mmAuth,\n ...fetchParams\n}: CreateKgwAuthenticatedBlobGatewayParams): BlobGateway {\n const storageAuth =\n mmAuth ?? (isMmTokenAuth(fetchParams.signer) ? fetchParams.signer : undefined);\n\n return new BlobGateway({\n url,\n maxFetchBytes,\n accessToken: storageAuth?.accessToken,\n fetchFn: createKgwAuthenticatedFetch(fetchParams),\n });\n}\n\nexport function createKgwAuthenticatedFetch({\n kwilClient,\n signer,\n fetchFn = fetch,\n isAuthFailure = defaultKgwAuthFailurePredicate,\n}: CreateKgwAuthenticatedFetchParams): typeof fetch {\n const nodeKwil = getNodeKwilClient(kwilClient);\n // Coalesce in-flight re-auths. Node isn't multi-threaded, but concurrent awaits still\n // interleave: two fetches can both see an auth failure and both call refreshCookie before\n // either finishes. Without this, that would kick off two authenticateKGWAndSetCookie calls.\n // See \"shares one refresh across parallel auth failures\".\n let refreshPromise: Promise<string> | undefined;\n\n const refreshCookie = async (): Promise<string> => {\n refreshPromise ??= nodeKwil.authenticateKGWAndSetCookie(signer).finally(() => {\n refreshPromise = undefined;\n });\n\n return refreshPromise;\n };\n\n const ensureCookie = async (): Promise<{ cookie: string; refreshed: boolean }> => {\n const existingCookie = nodeKwil.getKgwCookie();\n if (existingCookie) {\n return { cookie: existingCookie, refreshed: false };\n }\n\n return { cookie: await refreshCookie(), refreshed: true };\n };\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const { cookie } = await ensureCookie();\n const bufferedRequest = await bufferRequestBody(input, init);\n const response = await fetchFn(\n ...withCookie(input, withMaterializedBody(bufferedRequest), cookie),\n );\n\n const probe = authFailureProbe(response);\n if (!(await isAuthFailure(probe.response))) {\n return response;\n }\n\n // Discard the failed response so an unread body doesn't keep streaming.\n await discardUnreadBodies(probe.discardResponses);\n const refreshedCookie = await refreshCookie();\n return fetchFn(...withCookie(input, withMaterializedBody(bufferedRequest), refreshedCookie));\n };\n}\n\ntype AuthFailureProbe = {\n response: Response;\n discardResponses: Response[];\n};\n\n/**\n * Body is one-shot. Only clone when the default predicate might call `.json()`\n * (JSON content-type). Cloning a large blob response would tee the stream and\n * risk buffering the download on an abandoned branch — and in Node, canceling\n * that unread tee branch hangs.\n *\n * When a cloned response is thrown away after an auth failure, cancel both tee\n * branches together; canceling only one branch can wait forever for the other.\n */\nfunction authFailureProbe(response: Response): AuthFailureProbe {\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n const probe = response.clone();\n return { response: probe, discardResponses: [response, probe] };\n }\n\n return { response, discardResponses: [response] };\n}\n\nasync function discardUnreadBodies(responses: Response[]): Promise<void> {\n await Promise.all(responses.map(discardUnreadBody));\n}\n\nasync function discardUnreadBody(response: Response): Promise<void> {\n if (response.bodyUsed || !response.body) {\n return;\n }\n\n try {\n await response.body.cancel();\n } catch {\n // Already locked/closed by a concurrent reader.\n }\n}\n\ntype BufferedFormDataEntry =\n | { key: string; value: string }\n | { key: string; value: ArrayBuffer; fileName: string; type: string };\n\ntype BufferedBody =\n | { kind: \"body\"; value: BodyInit }\n | { kind: \"form-data\"; entries: BufferedFormDataEntry[] };\n\ntype BufferedRequestBody = {\n requestInit: RequestInit | undefined;\n bufferedBody?: BufferedBody;\n};\n\nasync function bufferRequestBody(\n input: RequestInfo | URL,\n init?: RequestInit,\n): Promise<BufferedRequestBody> {\n if (init?.body != null) {\n return {\n requestInit: init,\n bufferedBody: await bufferBody(init.body),\n };\n }\n\n if (input instanceof Request && input.body != null) {\n const requestClone = input.clone();\n return {\n requestInit: {\n ...init,\n method: init?.method ?? input.method,\n },\n bufferedBody: await bufferBody(requestClone.body!),\n };\n }\n\n return { requestInit: init };\n}\n\nfunction withMaterializedBody({\n requestInit,\n bufferedBody,\n}: BufferedRequestBody): RequestInit | undefined {\n if (!bufferedBody) {\n return requestInit;\n }\n\n return {\n ...requestInit,\n body: materializeBody(bufferedBody),\n };\n}\n\nasync function bufferBody(body: BodyInit): Promise<BufferedBody> {\n if (\n typeof body === \"string\" ||\n body instanceof Blob ||\n body instanceof ArrayBuffer ||\n body instanceof URLSearchParams\n ) {\n return { kind: \"body\", value: body };\n }\n\n if (ArrayBuffer.isView(body)) {\n return {\n kind: \"body\",\n value: new Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n };\n }\n\n if (body instanceof FormData) {\n const entries: Promise<BufferedFormDataEntry>[] = [];\n\n body.forEach((value, key) => {\n entries.push(bufferFormDataEntry(key, value));\n });\n\n return { kind: \"form-data\", entries: await Promise.all(entries) };\n }\n\n if (body instanceof ReadableStream) {\n return {\n kind: \"body\",\n value: await new Response(body).arrayBuffer(),\n };\n }\n\n return { kind: \"body\", value: body };\n}\n\nasync function bufferFormDataEntry(\n key: string,\n value: FormDataEntryValue,\n): Promise<BufferedFormDataEntry> {\n if (typeof value === \"string\") {\n return { key, value };\n }\n\n return {\n key,\n value: await new Response(value).arrayBuffer(),\n fileName: value instanceof File ? value.name : \"blob\",\n type: value.type || \"application/octet-stream\",\n };\n}\n\nfunction materializeBody(bufferedBody: BufferedBody): BodyInit {\n if (bufferedBody.kind === \"body\") {\n return bufferedBody.value;\n }\n\n const formData = new FormData();\n\n for (const entry of bufferedBody.entries) {\n if (\"fileName\" in entry) {\n formData.append(entry.key, new Blob([entry.value], { type: entry.type }), entry.fileName);\n } else {\n formData.append(entry.key, entry.value);\n }\n }\n\n return formData;\n}\n\nfunction getNodeKwilClient(kwilClient: KwilActionClient): KgwSessionNodeKwil {\n if (!(kwilClient.client instanceof NodeKwil)) {\n throw new Error(\"KGW authenticated fetch can only be created from a NodeKwil client\");\n }\n\n if (!hasKgwSessionHelpers(kwilClient.client)) {\n throw new Error(\"NodeKwil client does not expose KGW session cookie helpers\");\n }\n\n return kwilClient.client;\n}\n\nfunction hasKgwSessionHelpers(client: NodeKwil): client is KgwSessionNodeKwil {\n const maybeClient = client as Partial<KgwSessionNodeKwil>;\n\n return (\n typeof maybeClient.getKgwCookie === \"function\" &&\n typeof maybeClient.authenticateKGWAndSetCookie === \"function\"\n );\n}\n\nfunction withCookie(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n cookie: string,\n): Parameters<typeof fetch> {\n const headers = new Headers(input instanceof Request ? input.headers : undefined);\n\n if (init?.headers) {\n new Headers(init.headers).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n\n headers.set(\"Cookie\", cookie);\n\n return [input, { ...init, headers }];\n}\n\nasync function defaultKgwAuthFailurePredicate(response: Response): Promise<boolean> {\n if (response.status === 401) {\n return true;\n }\n\n const contentType = response.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return false;\n }\n\n try {\n const body = (await response.json()) as { error?: { code?: number } };\n return body.error?.code === KGW_AUTH_ERROR_CODE;\n } catch {\n return false;\n }\n}\n","// Network configuration mapping\nconst NEAR_NETWORKS = {\n mainnet: {\n networkId: \"mainnet\",\n nodeUrl: \"https://rpc.mainnet.near.org\",\n },\n testnet: {\n networkId: \"testnet\",\n nodeUrl: \"https://rpc.testnet.near.org\",\n },\n betanet: {\n networkId: \"betanet\",\n nodeUrl: \"https://rpc.betanet.near.org\",\n },\n shardnet: {\n networkId: \"shardnet\",\n nodeUrl: \"https://rpc.shardnet.near.org\",\n },\n} as const;\n\n// Function to detect NEAR network from account ID\nexport const detectNearNetwork = (accountId: string): keyof typeof NEAR_NETWORKS => {\n if (accountId.endsWith(\".near\")) return \"mainnet\";\n if (accountId.endsWith(\".testnet\")) return \"testnet\";\n if (accountId.endsWith(\".betanet\")) return \"betanet\";\n if (accountId.endsWith(\".shardnet\")) return \"shardnet\";\n\n // Default to testnet for development, mainnet for production\n return \"testnet\";\n};\n\n// Function to get connection config based on account ID\nexport const getNearConnectionConfig = (\n accountId: string,\n): { networkId: string; nodeUrl: string } => {\n const network = detectNearNetwork(accountId);\n const networkConfig = NEAR_NETWORKS[network];\n\n return {\n networkId: networkConfig.networkId,\n nodeUrl: networkConfig.nodeUrl,\n };\n};\n","import type { Store } from \"@idos-network/utils/store\";\nimport type {\n Wallet as NearWallet,\n SignedMessage,\n SignMessageParams,\n} from \"@near-wallet-selector/core\";\nimport type { connect as connectT } from \"near-api-js\";\nimport type { AccessKeyList } from \"near-api-js/lib/providers/provider\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\nimport {\n base64Decode,\n binaryWriteUint16BE,\n bs58Decode,\n bytesConcat,\n hexEncode,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getNearConnectionConfig } from \"./get-config\";\nimport { nep413SignHash, serializeKwilNep413 } from \"./nep413\";\n\nconst NEAR_WALLET_TYPES: string[] = [\n \"browser\",\n \"injected\",\n \"instant-link\",\n \"hardware\",\n \"bridge\",\n] satisfies NearWallet[\"type\"][];\n\nexport function looksLikeNearWallet(signer: unknown): signer is NearWallet {\n return (\n signer !== null &&\n typeof signer === \"object\" &&\n \"id\" in signer &&\n \"metadata\" in signer &&\n \"type\" in signer &&\n typeof signer.type === \"string\" &&\n NEAR_WALLET_TYPES.includes(signer.type)\n );\n}\n\nclass KwilNonce {\n bytes: Uint8Array;\n\n constructor(length = 32) {\n // We're in the browser, so there's a window.crypto for sure.\n /* global crypto */\n this.bytes = crypto.getRandomValues(new Uint8Array(length));\n }\n\n get clampUTF8() {\n return this.bytes.map((byte) => byte & 127);\n }\n}\n\n/**\n * Creates a signer function that can be used to sign messages with a NEAR wallet\n */\nfunction createNearWalletSigner(\n wallet: NearWallet,\n recipient: string,\n): (message: string | Uint8Array) => Promise<Uint8Array> {\n return async (message: string | Uint8Array): Promise<Uint8Array> => {\n const messageString = typeof message === \"string\" ? message : utf8Decode(message);\n\n if (!wallet.signMessage) {\n throw new Error(\"Only wallets with signMessage are supported.\");\n }\n\n const nonceSuggestion = Buffer.from(new KwilNonce(32).bytes);\n\n const {\n nonce = nonceSuggestion,\n signature,\n // @ts-expect-error Signatures don't seem to be updated for NEP413 yet.\n callbackUrl,\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Only non-signing wallets return void.\n } = (await (\n wallet.signMessage as (\n _: SignMessageParams,\n ) => Promise<SignedMessage & { nonce?: Uint8Array }>\n )({\n message: messageString,\n recipient,\n nonce: nonceSuggestion,\n }))!;\n\n const nep413BorshPayload = serializeKwilNep413({\n message: messageString,\n nonce: Array.from(nonce),\n recipient,\n callbackUrl,\n });\n const result = bytesConcat(\n binaryWriteUint16BE(nep413BorshPayload.length),\n nep413BorshPayload,\n base64Decode(signature),\n );\n\n return result;\n };\n}\n\nexport function implicitAddressFromPublicKey(publicKey: string): string {\n const key_without_prefix = publicKey.replace(/^ed25519:/, \"\");\n return hexEncode(bs58Decode(key_without_prefix), true);\n}\n\nexport async function getNearFullAccessPublicKeys(\n namedAddress: string,\n): Promise<string[] | undefined> {\n let connect: typeof connectT;\n try {\n connect = (await import(\"near-api-js\")).connect;\n } catch (_e) {\n throw new Error(\"Can't load near-api-js\");\n }\n const connectionConfig = getNearConnectionConfig(namedAddress);\n const nearConnection = await connect(connectionConfig);\n\n try {\n const response: AccessKeyList = await nearConnection.connection.provider.query({\n request_type: \"view_access_key_list\",\n finality: \"final\",\n account_id: namedAddress,\n });\n return response.keys\n .filter((element) => element.access_key.permission === \"FullAccess\")\n ?.map((i) => i.public_key);\n } catch {\n // `Near` failed if namedAddress contains uppercase symbols\n return;\n }\n}\n\ntype NearRedirect = {\n accountId?: string;\n publicKey?: string;\n signature?: string;\n error?: string;\n};\n\nfunction parseNearRedirect(hash: string): NearRedirect {\n const params = new URLSearchParams(hash.startsWith(\"#\") ? hash.slice(1) : hash);\n const signature = params.get(\"signature\");\n return {\n accountId: params.get(\"accountId\") ?? undefined,\n publicKey: params.get(\"publicKey\") ?? undefined,\n // URLSearchParams decodes a literal \"+\" as a space. NEP-413 signatures are base64.\n signature: signature?.replaceAll(\" \", \"+\"),\n error: params.get(\"error\") ?? undefined,\n };\n}\n\nfunction takeNearRedirect(): NearRedirect {\n const redirect = parseNearRedirect(window.location.hash);\n if (!redirect.accountId && !redirect.publicKey && !redirect.signature && !redirect.error) {\n return redirect;\n }\n\n const params = new URLSearchParams(window.location.hash.slice(1));\n for (const key of [\"accountId\", \"publicKey\", \"signature\", \"error\", \"state\"]) params.delete(key);\n const rest = params.toString();\n window.history.replaceState(\n null,\n \"\",\n `${window.location.pathname}${window.location.search}${rest ? `#${rest}` : \"\"}`,\n );\n return redirect;\n}\n\nfunction verifyNep413Signature(\n message: string,\n nonce: Uint8Array,\n recipient: string,\n callbackUrl: string,\n signature: string,\n publicKey: string,\n): boolean {\n const pieces = publicKey.split(\":\");\n if (pieces.length !== 2 || pieces[0] !== \"ed25519\" || !pieces[1] || nonce.length !== 32) {\n return false;\n }\n\n try {\n const publicKeyBytes = bs58Decode(pieces[1]);\n const signatureBytes = base64Decode(signature);\n if (publicKeyBytes.length !== 32 || signatureBytes.length !== 64) return false;\n\n return nacl.sign.detached.verify(\n nep413SignHash({ message, nonce, recipient, callbackUrl }),\n signatureBytes,\n publicKeyBytes,\n );\n } catch {\n return false;\n }\n}\n\n// The hash is attacker-controlled. A signature is only the wallet's if it verifies\n// against the request we stored before the redirect, for a full-access key of this account.\nasync function trustedNearRedirect(\n redirect: NearRedirect,\n currentAddress: string,\n recipient: string,\n store: Store,\n): Promise<{ signature: string; publicKey: string } | undefined> {\n if (\n redirect.error ||\n !redirect.signature ||\n !redirect.publicKey ||\n redirect.accountId !== currentAddress\n ) {\n return;\n }\n\n const message = await store.get<string>(\"sign-last-message\");\n const savedNonce = await store.get<number[] | Uint8Array>(\"sign-last-nonce\");\n const callbackUrl = await store.get<string>(\"sign-last-url\");\n if (!message || !savedNonce || !callbackUrl) return;\n\n const nonce = Uint8Array.from(savedNonce);\n if (\n !verifyNep413Signature(\n message,\n nonce,\n recipient,\n callbackUrl,\n redirect.signature,\n redirect.publicKey,\n )\n ) {\n return;\n }\n\n const keys = await getNearFullAccessPublicKeys(currentAddress);\n if (!keys?.includes(redirect.publicKey)) return;\n\n return { signature: redirect.signature, publicKey: redirect.publicKey };\n}\n\nexport async function signNearMessage(\n wallet: NearWallet,\n message: string,\n recipient = \"idos.network\",\n): Promise<string> {\n const signer = createNearWalletSigner(wallet, recipient);\n const signedPayload = await signer(message);\n return hexEncode(signedPayload);\n}\n\nexport async function createNearWalletKwilSigner(\n wallet: NearWallet,\n currentAddress: string,\n store: Store,\n kwilClient: KwilActionClient,\n recipient = \"idos.network\",\n): Promise<{ kwilSigner: KwilSigner; publicKey: string }> {\n if (!wallet.signMessage) throw new Error(\"Only wallets with signMessage are supported.\");\n\n if (wallet.id === \"my-near-wallet\") {\n const redirect = takeNearRedirect();\n const trusted = await trustedNearRedirect(redirect, currentAddress, recipient, store);\n\n if (trusted) {\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", trusted.publicKey);\n }\n\n const signMessageOriginal = wallet.signMessage.bind(wallet);\n\n wallet.signMessage = async ({\n message,\n recipient: signRecipient,\n }: SignMessageParams): Promise<SignedMessage & { nonce?: Uint8Array }> => {\n if (redirect.error) return Promise.reject();\n\n const lastMessage = await store.get<string>(\"sign-last-message\");\n const lastNonce = await store.get<Uint8Array>(\"sign-last-nonce\");\n\n if (trusted && message === lastMessage && lastNonce) {\n const nonce = Buffer.from(lastNonce);\n const callbackUrl = await store.get<string>(\"sign-last-url\");\n\n return Promise.resolve({\n accountId: currentAddress,\n publicKey: trusted.publicKey,\n signature: trusted.signature,\n nonce,\n message,\n callbackUrl,\n } as SignedMessage);\n }\n\n const callbackUrl = window.location.href;\n const nonce = Buffer.from(new KwilNonce(32).clampUTF8);\n\n await store.set(\"sign-last-message\", message);\n await store.set(\"sign-last-nonce\", Array.from(nonce));\n await store.set(\"sign-last-url\", callbackUrl);\n\n signMessageOriginal({ message, nonce, recipient: signRecipient, callbackUrl });\n\n return new Promise(() => ({}) as SignedMessage);\n };\n }\n\n const storedAddress = await store.get<string>(\"signer-address\");\n\n let publicKey = await store.get<string>(\"signer-public-key\");\n\n if (storedAddress !== currentAddress || !publicKey) {\n store.reset();\n // To avoid re-using the old signer's kgw cookie.\n // When kwil-js supports multi cookies, we can remove this.\n await kwilClient.client.auth.logoutKGW();\n\n const message = \"idOS authentication\";\n const nonce = Buffer.from(new KwilNonce(32).bytes);\n const signResult = await wallet.signMessage({ message, recipient, nonce });\n if (!signResult) throw new Error(\"signMessage returned no result\");\n ({ publicKey } = signResult);\n\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", publicKey);\n }\n\n const signer = createNearWalletSigner(wallet, recipient);\n\n return {\n kwilSigner: new KwilSigner(signer, implicitAddressFromPublicKey(publicKey), \"nep413\"),\n publicKey,\n };\n}\n","import type * as GemWallet from \"@gemwallet/api\";\nimport type { Store } from \"@idos-network/utils/store\";\nimport type { Xumm } from \"xumm\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getXrpTxHash } from \"./utils\";\n\nexport async function createXrpKwilSigner(\n wallet: Xumm | typeof GemWallet,\n currentAddress: string,\n store: Store,\n kwilClient: KwilActionClient,\n walletPublicKey: string,\n): Promise<KwilSigner> {\n const storedAddress = await store.get<string>(\"signer-address\");\n const storePublicKey = await store.get<string>(\"signer-public-key\");\n\n if (storedAddress !== currentAddress || (storePublicKey && storePublicKey !== walletPublicKey)) {\n try {\n // HEADS UP: for some reason logoutKGW fails on xrp\n // storePublicKey && await kwilClient.client.auth.logoutKGW();\n console.log(\"logoutKGW\", kwilClient);\n } catch (error) {\n console.error(\"Failed to logout KGW:\", error);\n }\n }\n\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", walletPublicKey);\n\n const signer = async (message: string | Uint8Array): Promise<Uint8Array> => {\n const signature = await getXrpTxHash(message, wallet);\n // Buffer.from(_, \"hex\") silently truncates at the first non-hex char, so reject it up front.\n if (!signature || !/^(?:[0-9a-f]{2})+$/i.test(signature)) {\n throw new Error(\"Failed to sign transaction with XRP\");\n }\n return Buffer.from(signature, \"hex\");\n };\n\n return new KwilSigner(signer, walletPublicKey, \"xrpl\");\n}\n","import type { Store } from \"@idos-network/utils/store\";\nimport type { Wallet as NearWallet } from \"@near-wallet-selector/core\";\nimport type { Keypair as StellarKeypair } from \"@stellar/stellar-sdk\";\nimport type { Wallet as EthersWallet, JsonRpcSigner } from \"ethers\";\nimport type { KeyPair as NearKeyPair } from \"near-api-js\";\nimport type { KeyPair as XrpKeyPair } from \"ripple-keypairs/src/types\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\nimport { base64UrlEncode, bs58Encode, hexDecode, hexEncode } from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nimport type { WalletType } from \"./actions\";\nimport type { KwilActionClient } from \"./create-kwil-client\";\nimport type { MmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nimport { FaceSignSignerProvider } from \"./facesign/facesign-signer\";\nimport { isMmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\nimport {\n createNearWalletKwilSigner,\n implicitAddressFromPublicKey,\n looksLikeNearWallet,\n} from \"./near/create-near-wallet-kwil-signer\";\nimport { kwilNep413Signer } from \"./near/nep413\";\nimport { createXrpKwilSigner } from \"./xrp/signer\";\nimport { getXrpPublicKey, looksLikeXrpWallet } from \"./xrp/utils\";\n\nexport { KwilSigner } from \"@idos-network/kwil-js\";\nexport type Wallet =\n | EthersWallet\n | JsonRpcSigner\n | NearWallet\n | CustomKwilSigner\n | MmTokenAuth\n | FaceSignSignerProvider;\n\n/**\n * Helper function to check if the given object is a `nacl.SignKeyPair`.\n */\nfunction isNaclSignKeyPair(object: unknown): object is nacl.SignKeyPair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicKey\" in object &&\n object.publicKey instanceof Uint8Array &&\n object.publicKey.length === nacl.sign.publicKeyLength &&\n \"secretKey\" in object &&\n object.secretKey instanceof Uint8Array &&\n object.secretKey.length === nacl.sign.secretKeyLength\n );\n}\n\n/**\n * Helper function to check if the given object is a NEAR KeyPair.\n */\nfunction isNearKeyPair(object: unknown): object is NearKeyPair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"getPublicKey\" in object &&\n \"sign\" in object &&\n typeof object.getPublicKey === \"function\" &&\n typeof object.sign === \"function\"\n );\n}\n\n/**\n * Helper function to check if the given object is a Stellar Keypair.\n */\nfunction isStellarKeyPair(object: unknown): object is StellarKeypair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicKey\" in object &&\n \"sign\" in object &&\n \"canSign\" in object &&\n typeof object.publicKey === \"function\" &&\n typeof object.sign === \"function\" &&\n typeof object.canSign === \"function\"\n );\n}\n\nexport interface CustomKwilSigner extends KwilSigner {\n publicAddress: string;\n signatureType: string;\n publicKey: string;\n walletType: string;\n signMessage: (message: Uint8Array | string) => Promise<Uint8Array>;\n}\n\nfunction isCustomKwilSigner(object: unknown): object is CustomKwilSigner {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicAddress\" in object &&\n \"signatureType\" in object &&\n \"publicKey\" in object &&\n \"signMessage\" in object\n );\n}\n\n/**\n * Helper function to check if the given object is a XRP KeyPair (Server key pairs only).\n */\nfunction isXrplKeyPair(object: unknown): object is XrpKeyPair {\n return !!object && typeof object === \"object\" && \"privateKey\" in object && \"publicKey\" in object;\n}\n\nexport type KwilSignerType =\n | NearKeyPair\n | EthersWallet\n | nacl.SignKeyPair\n | JsonRpcSigner\n | StellarKeypair\n | XrpKeyPair\n | MmTokenAuth;\n\nexport type SignerAddress = string;\nexport type SignerPublicKey = string | undefined;\n\n/**\n * Creates a `KwilSigner` and its associated `SignerAddress`.\n *\n * This function is explicitly marked as being for backend use only because it doesn't reset\n * the KGW cookie when logging out and re-logging in with a different wallet.\n */\nexport async function createServerKwilSigner(\n signer: KwilSignerType,\n): Promise<[KwilSigner, SignerAddress]> {\n if (isMmTokenAuth(signer)) {\n return [signer, base64UrlEncode(signer.identifier)];\n }\n\n if (isNaclSignKeyPair(signer)) {\n return [\n new KwilSigner(\n async (msg: Uint8Array) => nacl.sign.detached(msg, signer.secretKey),\n signer.publicKey,\n \"ed25519\",\n ),\n implicitAddressFromPublicKey(bs58Encode(signer.publicKey)),\n ];\n }\n\n if (isNearKeyPair(signer)) {\n const rawPublicKey = signer.getPublicKey().toString();\n const hexPublicKey = implicitAddressFromPublicKey(rawPublicKey);\n return [\n new KwilSigner(kwilNep413Signer(\"idos-issuer\")(signer), hexPublicKey, \"nep413\"),\n rawPublicKey,\n ];\n }\n\n if (isStellarKeyPair(signer)) {\n const publicKeyString = signer.publicKey();\n const rawPublicKey = signer.rawPublicKey();\n return [\n new KwilSigner(\n async (msg: Uint8Array) => signer.sign(Buffer.from(msg)),\n rawPublicKey,\n \"ed25519\",\n ),\n publicKeyString,\n ];\n }\n\n if (isXrplKeyPair(signer)) {\n let xrpKeypair: typeof import(\"ripple-keypairs\");\n\n try {\n xrpKeypair = await import(\"ripple-keypairs\");\n } catch (e) {\n throw new Error(\"Can't load ripple-keypairs\", { cause: e });\n }\n\n return [\n new KwilSigner(\n async (msg: Uint8Array) => hexDecode(xrpKeypair.sign(hexEncode(msg), signer.privateKey)),\n signer.publicKey,\n \"xrpl\",\n ),\n signer.publicKey,\n ];\n }\n\n if (\"address\" in signer) {\n return [new KwilSigner(signer, signer.address), signer.address];\n }\n\n // Force the check that `signer` is never.\n // If these lines start complaining, that means we're missing an `if` above.\n return ((_: never) => {\n throw new Error(\"Invalid `signer` type\");\n })(signer);\n}\n\nexport async function createClientKwilSigner(\n store: Store,\n kwilClient: KwilActionClient,\n wallet: Wallet,\n): Promise<[KwilSigner, SignerAddress, SignerPublicKey, WalletType]> {\n if (\"connect\" in wallet && \"address\" in wallet) {\n // oxlint-disable-next-line no-param-reassign -- Narrowing the type on purpose\n wallet = wallet as unknown as JsonRpcSigner;\n const currentAddress = await wallet.getAddress();\n\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== currentAddress) {\n // To avoid re-using the old signer's kgw cookie.\n // When kwil-js supports multi cookies, we can remove this.\n store.set(\"signer-address\", currentAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [new KwilSigner(wallet, currentAddress), currentAddress, undefined, \"EVM\"];\n }\n\n if (looksLikeNearWallet(wallet)) {\n const accounts = await wallet.getAccounts();\n const { kwilSigner, publicKey } = await createNearWalletKwilSigner(\n wallet,\n accounts[0].accountId,\n store,\n kwilClient,\n );\n\n return [kwilSigner, accounts[0].accountId, publicKey, \"NEAR\"];\n }\n\n if (looksLikeXrpWallet(wallet)) {\n const { address: currentAddress, publicKey: walletPublicKey } = (await getXrpPublicKey(\n wallet,\n )) as { address: string; publicKey: string };\n if (!currentAddress) {\n throw new Error(\"Failed to get XRP address\");\n }\n\n return [\n await createXrpKwilSigner(wallet, currentAddress, store, kwilClient, walletPublicKey),\n currentAddress,\n walletPublicKey,\n \"XRPL\",\n ];\n }\n\n if (isMmTokenAuth(wallet)) {\n const currentAddress = base64UrlEncode(wallet.identifier);\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== currentAddress) {\n // A different MM signing identity must not re-use the previous KGW cookie.\n store.set(\"signer-address\", currentAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [wallet, currentAddress, currentAddress, \"MM\"];\n }\n\n if (isCustomKwilSigner(wallet) || wallet instanceof FaceSignSignerProvider) {\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== wallet.publicAddress) {\n store.set(\"signer-address\", wallet.publicAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [\n new KwilSigner(\n async (msg: Uint8Array) => wallet.signMessage(msg),\n wallet.publicAddress,\n \"ed25519\",\n ),\n wallet.publicAddress,\n wallet.publicKey,\n wallet.walletType as WalletType,\n ];\n }\n\n // Force the check that `signer` is `never`.\n // If these lines start complaining, that means we're missing an `if` above.\n return ((_: never) => {\n throw new Error(\"Invalid `signer` type\");\n })(wallet);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["KwilSigner","KwilSigner","KwilSigner","KwilSigner"],"sources":["../src/wait-for-kwil-tx.ts","../src/create-kwil-client.ts","../src/mm-token/create-mm-token-kwil-signer.ts","../src/create-kgw-authenticated-fetch.ts","../src/near/get-config.ts","../src/near/create-near-wallet-kwil-signer.ts","../src/xrp/signer.ts","../src/create-kwil-signer.ts"],"sourcesContent":["const KWIL_TX_POLL_DEADLINE_MS = 90_000;\nconst INITIAL_POLL_INTERVAL_MS = 300;\nconst POLL_BACKOFF_FACTOR = 1.5;\nconst MAX_POLL_INTERVAL_MS = 2_000;\nconst MAX_POLL_JITTER_MS = 100;\n\nexport type KwilTxInfo = {\n height: number;\n tx_result: {\n code: number;\n log: string;\n };\n};\n\nexport class KwilTxFailedError extends Error {\n readonly name = \"KwilTxFailedError\";\n\n constructor(\n readonly txHash: string,\n readonly code: number,\n readonly log: string,\n readonly height: number,\n ) {\n super(`Kwil transaction ${txHash} failed at height ${height} (code ${code}): ${log}`);\n }\n}\n\nexport class KwilTxPollTimeoutError extends Error {\n readonly name = \"KwilTxPollTimeoutError\";\n\n constructor(\n readonly txHash: string,\n readonly deadlineMs: number,\n options?: { cause?: unknown },\n ) {\n const lastError =\n options?.cause instanceof Error\n ? options.cause.message\n : options?.cause != null\n ? String(options.cause)\n : undefined;\n super(\n lastError\n ? `Timed out after ${deadlineMs}ms waiting for Kwil transaction ${txHash}: last error: ${lastError}`\n : `Timed out after ${deadlineMs}ms waiting for Kwil transaction ${txHash}`,\n options?.cause !== undefined ? { cause: options.cause } : undefined,\n );\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction nextPollIntervalMs(currentIntervalMs: number): number {\n return Math.min(currentIntervalMs * POLL_BACKOFF_FACTOR, MAX_POLL_INTERVAL_MS);\n}\n\nfunction pollIntervalWithJitter(intervalMs: number): number {\n return intervalMs + Math.floor(Math.random() * (MAX_POLL_JITTER_MS + 1));\n}\n\nfunction isTxFinalized(txInfo: KwilTxInfo): boolean {\n return txInfo.height > 0;\n}\n\nexport async function waitForKwilTx(\n txInfo: (txHash: string) => Promise<{ data?: KwilTxInfo }>,\n txHash: string,\n deadlineMs: number = KWIL_TX_POLL_DEADLINE_MS,\n): Promise<void> {\n const deadlineAt = Date.now() + deadlineMs;\n let intervalMs = INITIAL_POLL_INTERVAL_MS;\n let lastPollError: unknown;\n\n while (Date.now() < deadlineAt) {\n let data: KwilTxInfo | undefined;\n\n // Transient poll failures (e.g. \"not found\" before the node indexes the tx) are\n // recorded and retried. Terminal tx failures are decided below, outside this catch.\n try {\n data = (await txInfo(txHash)).data;\n } catch (error) {\n lastPollError = error;\n }\n\n // height > 0 means the tx was included. Then code 0 is success; anything else is final failure.\n if (data && isTxFinalized(data)) {\n if (data.tx_result.code !== 0) {\n throw new KwilTxFailedError(txHash, data.tx_result.code, data.tx_result.log, data.height);\n }\n return;\n }\n\n // Not finalized yet (or last poll errored) — back off and try again until the deadline.\n const waitMs = pollIntervalWithJitter(intervalMs);\n const remainingMs = deadlineAt - Date.now();\n if (remainingMs <= 0) {\n break;\n }\n\n await sleep(Math.min(waitMs, remainingMs));\n intervalMs = nextPollIntervalMs(intervalMs);\n }\n\n throw new KwilTxPollTimeoutError(\n txHash,\n deadlineMs,\n lastPollError !== undefined ? { cause: lastPollError } : undefined,\n );\n}\n","import type { ActionBody, CallBody, PositionalParams } from \"@idos-network/kwil-js/action\";\nimport type { Config } from \"@idos-network/kwil-js/config\";\nimport type { DataInfo } from \"@idos-network/kwil-js/database\";\n\nimport { type KwilSigner, NodeKwil, WebKwil } from \"@idos-network/kwil-js\";\nimport invariant from \"tiny-invariant\";\n\nimport type { ActionSchemaElement } from \"./actions\";\n\nimport { actionSchema } from \"./actions\";\nimport { waitForKwilTx } from \"./wait-for-kwil-tx\";\n\nexport { KwilTxFailedError, KwilTxPollTimeoutError } from \"./wait-for-kwil-tx\";\n\ntype CreateKwilClientParams = {\n chainId?: string;\n nodeUrl: string;\n};\n\ntype KwilActions = typeof actionSchema;\ntype ActionName = keyof KwilActions;\n\ntype AllKwilCallAction = {\n [Name in ActionName]: {\n name: Name;\n // oxlint-disable-next-line typescript/no-explicit-any -- This is fine\n inputs: Record<KwilActions[Name][number][\"name\"], any>;\n };\n};\n\ntype KwilCallActionRequestParams = AllKwilCallAction[ActionName];\n\ntype AllKwilExecuteAction = {\n [Name in ActionName]: AllKwilCallAction[Name] & { description: string };\n};\n\ntype KwilExecuteActionRequestParams = AllKwilExecuteAction[ActionName];\n\n/**\n * A client for interacting with kwil with type-safe abstractions for `call` and `execute`.\n * Has utility methods for creating actions and setting a signer.\n */\nexport class KwilActionClient {\n signer?: KwilSigner;\n readonly client: NodeKwil | WebKwil;\n\n constructor(client: NodeKwil | WebKwil) {\n this.client = client;\n }\n\n #createActionInputs(actionName: string, params: Record<string, unknown> = {}): PositionalParams {\n if (!params || !Object.keys(params).length) return [];\n\n const args = (actionSchema as Record<string, readonly ActionSchemaElement[]>)[actionName];\n\n return args.map(({ name }) => {\n const value = params[name];\n // Handle falsy values appropriately\n if (value === \"\" || value === 0) return value;\n return value ?? null;\n }) as PositionalParams;\n }\n\n #actionTypes(actionName: string): DataInfo[] {\n const args = actionSchema[actionName];\n return args.map((arg) => arg.type);\n }\n\n /**\n * Calls an action on the kwil nodes. This similar to `GET` like request.\n */\n async call<T = unknown>(\n params: KwilCallActionRequestParams,\n signer: KwilSigner | undefined = this.signer,\n ): Promise<T> {\n const action: CallBody = {\n name: params.name,\n namespace: \"main\",\n inputs: this.#createActionInputs(params.name, params.inputs),\n types: this.#actionTypes(params.name),\n };\n\n const response = await this.client.call(action as CallBody, signer);\n return response?.data?.result as T;\n }\n\n /**\n * Executes an action on the kwil nodes. This similar to `POST` like request.\n *\n * When `synchronous` is true (default), the tx is broadcast without blocking the node,\n * then confirmed by polling `txInfo` with exponential backoff.\n */\n async execute(\n params: KwilExecuteActionRequestParams,\n signer: KwilSigner | undefined = this.signer,\n synchronous = true,\n ): Promise<string> {\n invariant(signer, \"Signer is not set, you must set it before executing an action\");\n const action: ActionBody = {\n name: params.name,\n namespace: \"main\",\n description: params.description,\n inputs: [this.#createActionInputs(params.name, params.inputs)],\n types: this.#actionTypes(params.name),\n };\n const response = await this.client.execute(action, signer, false);\n const txHash = response.data?.tx_hash;\n\n if (!txHash) {\n throw new Error(`Kwil execute \"${params.name}\" did not return a transaction hash`);\n }\n\n if (synchronous) {\n await this.waitForTx(txHash);\n }\n\n return txHash;\n }\n\n /**\n * Polls the node until a broadcast transaction is mined, or throws\n * `KwilTxFailedError` / `KwilTxPollTimeoutError`.\n *\n * Called through `this` rather than directly so that it is a seam an\n * instrumentation can wrap — the wait dominates the latency of `execute`.\n */\n async waitForTx(txHash: string): Promise<void> {\n await waitForKwilTx((hash) => this.client.txInfo(hash), txHash);\n }\n\n setSigner(signer: KwilSigner | undefined): void {\n this.signer = signer;\n }\n\n /**\n * Creates action inputs from the given parameters that are used in the action body.\n */\n}\n\nconst DEFAULT_TIMEOUT = 30_000;\n\nconst createKwilClient =\n (Cls: new (opts: Config) => NodeKwil | WebKwil) =>\n async ({ nodeUrl: kwilProvider, chainId }: CreateKwilClientParams): Promise<KwilActionClient> => {\n const _kwil = new Cls({ kwilProvider, chainId: \"\" });\n // oxlint-disable-next-line no-param-reassign -- Default value fallback\n chainId ||= (await _kwil.chainInfo({ disableWarning: true })).data?.chain_id;\n invariant(chainId, \"Can't discover `chainId`. You must pass it explicitly.\");\n\n const client = new KwilActionClient(\n new Cls({ kwilProvider, chainId, timeout: DEFAULT_TIMEOUT }),\n );\n\n return client;\n };\n\n/**\n * Create a kwil client for node.js environment\n */\nexport const createNodeKwilClient: (params: CreateKwilClientParams) => Promise<KwilActionClient> =\n createKwilClient(NodeKwil);\n\n/**\n * Create a kwil client for browser environment\n */\nexport const createWebKwilClient: (params: CreateKwilClientParams) => Promise<KwilActionClient> =\n createKwilClient(WebKwil);\n","import { KwilSigner } from \"@idos-network/kwil-js\";\nimport {\n base64UrlDecode,\n base64UrlEncode,\n utf8Decode,\n utf8Encode,\n} from \"@idos-network/utils/codecs\";\n\nconst ED25519_PUBLIC_KEY_BYTES = 32;\nconst ED25519_SIGNATURE_BYTES = 64;\n\n/** Decoded UKYC capability envelope. KGW signature data is base64url(JSON of this). */\nexport interface MmTokenEnvelope {\n payload: MmTokenPayload | Record<string, unknown>;\n signature: string;\n}\n\nexport interface MmTokenPayload {\n signing_public_key: string;\n storage_id?: string;\n [key: string]: unknown;\n}\n\n/**\n * One MM/UKYC capability, valid both as a KGW `mm_token` signer and as the\n * `Authorization: AccessToken …` credential for UKYC blob requests.\n */\nexport type MmTokenAuth = KwilSigner & {\n readonly mmTokenPayload: MmTokenPayload | Record<string, unknown>;\n /** Exact encoded envelope KGW and UKYC storage verify. Non-enumerable, so it stays out of logs. */\n readonly accessToken: string;\n /**\n * A capability signs its own envelope, never an arbitrary message. Declared so callers\n * handling a `Wallet` union can keep asking wallets for a message signature.\n */\n readonly signMessage?: undefined;\n};\n\nexport function isMmTokenAuth(value: unknown): value is MmTokenAuth {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"signatureType\" in value &&\n value.signatureType === \"mm_token\" &&\n \"identifier\" in value &&\n \"signer\" in value &&\n typeof (value as Partial<MmTokenAuth>).accessToken === \"string\"\n );\n}\n\n/** `storage_id` from the capability token used to construct this signer. */\nexport function mmTokenStorageId(signer: KwilSigner): string {\n const storageId = (signer as Partial<MmTokenAuth>).mmTokenPayload?.storage_id;\n if (typeof storageId !== \"string\" || !storageId.trim()) {\n throw new Error(\"mm_token payload is missing storage_id\");\n }\n return storageId.trim();\n}\n\nfunction isMmTokenEnvelope(value: unknown): value is MmTokenEnvelope {\n return (\n value !== null &&\n typeof value === \"object\" &&\n \"payload\" in value &&\n value.payload !== null &&\n typeof value.payload === \"object\" &&\n !Array.isArray(value.payload) &&\n \"signature\" in value &&\n typeof value.signature === \"string\"\n );\n}\n\nfunction parseJson<T>(bytes: Uint8Array, errorMessage: string): T {\n try {\n return JSON.parse(utf8Decode(bytes)) as T;\n } catch (error) {\n throw new Error(errorMessage, { cause: error });\n }\n}\n\nfunction decodeBase64Url(value: string, errorMessage: string): Uint8Array {\n try {\n return base64UrlDecode(value);\n } catch (error) {\n throw new Error(errorMessage, { cause: error });\n }\n}\n\n/**\n * Build the MM authentication object for one UKYC capability.\n *\n * Pass the MetaMask-issued capability token as a **base64url-encoded** envelope string\n * (what KGW verifies). A decoded `{ payload, signature }` object is also accepted and\n * will be re-encoded.\n *\n * `signMessage` always returns the UTF-8 bytes of that encoded string — KGW ignores the\n * request message and only verifies the envelope.\n */\nexport function createMmTokenAuth(encodedEnvelope: string | MmTokenEnvelope): MmTokenAuth {\n let encodedToken: string;\n let envelope: MmTokenEnvelope;\n\n if (typeof encodedEnvelope === \"string\") {\n const trimmed = encodedEnvelope.trim();\n if (!trimmed) {\n throw new Error(\"Invalid mm_token envelope: empty\");\n }\n encodedToken = trimmed;\n const envelopeBytes = decodeBase64Url(trimmed, \"Invalid mm_token envelope encoding\");\n const parsed = parseJson<unknown>(envelopeBytes, \"Invalid mm_token envelope JSON\");\n if (!isMmTokenEnvelope(parsed)) {\n throw new Error(\"Invalid mm_token envelope: expected payload object and signature string\");\n }\n envelope = parsed;\n } else {\n if (!isMmTokenEnvelope(encodedEnvelope)) {\n throw new Error(\"Invalid mm_token envelope: expected payload object and signature string\");\n }\n envelope = encodedEnvelope;\n encodedToken = base64UrlEncode(utf8Encode(JSON.stringify(envelope)));\n }\n\n // KGW Verify receives UTF-8 of the base64url string, not the decoded JSON bytes.\n const signatureData = utf8Encode(encodedToken);\n\n const tokenSignatureBytes = decodeBase64Url(\n envelope.signature,\n \"Invalid mm_token envelope signature encoding\",\n );\n if (tokenSignatureBytes.length !== ED25519_SIGNATURE_BYTES) {\n throw new Error(\n `Invalid mm_token signature length: expected ${ED25519_SIGNATURE_BYTES}, got ${tokenSignatureBytes.length}`,\n );\n }\n\n const signingPublicKey = envelope.payload.signing_public_key;\n if (typeof signingPublicKey !== \"string\") {\n throw new Error(\"Invalid mm_token payload: missing signing_public_key\");\n }\n\n const signingPublicKeyBytes = decodeBase64Url(\n signingPublicKey,\n \"Invalid mm_token signing_public_key encoding\",\n );\n\n if (signingPublicKeyBytes.length !== ED25519_PUBLIC_KEY_BYTES) {\n throw new Error(\n `Invalid mm_token signing_public_key length: expected ${ED25519_PUBLIC_KEY_BYTES}, got ${signingPublicKeyBytes.length}`,\n );\n }\n\n const auth = Object.assign(\n new KwilSigner(async () => signatureData.slice(), signingPublicKeyBytes, \"mm_token\"),\n { mmTokenPayload: envelope.payload },\n );\n\n return Object.defineProperty(auth, \"accessToken\", {\n value: encodedToken,\n enumerable: false,\n }) as MmTokenAuth;\n}\n","import { type KwilSigner, NodeKwil } from \"@idos-network/kwil-js\";\nimport { BlobGateway, type BlobGatewayParams } from \"@idos-network/utils/blob-gateway\";\n\nimport type { KwilActionClient } from \"./create-kwil-client\";\nimport type { MmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nimport { isMmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nconst KGW_AUTH_ERROR_CODE = -901;\n\n/** Return true when the response means KGW auth is missing/expired.\n * May read the body only for `application/json` responses (those are probed via a clone). */\nexport type KgwAuthFailurePredicate = (response: Response) => Promise<boolean> | boolean;\n\nexport type CreateKgwAuthenticatedFetchParams = {\n kwilClient: KwilActionClient;\n signer: KwilSigner;\n fetchFn?: typeof fetch;\n isAuthFailure?: KgwAuthFailurePredicate;\n};\n\nexport type CreateKgwAuthenticatedBlobGatewayParams = CreateKgwAuthenticatedFetchParams & {\n url: string;\n maxFetchBytes?: BlobGatewayParams[\"maxFetchBytes\"];\n /**\n * UKYC storage authority for blob requests. Defaults to `signer` when that signer\n * is itself an MM authentication object, so the capability is never passed twice.\n */\n mmAuth?: MmTokenAuth;\n};\n\ntype KgwSessionNodeKwil = NodeKwil & {\n authenticateKGWAndSetCookie(signer: KwilSigner): Promise<string>;\n getKgwCookie(): string | undefined;\n};\n\nexport function createKgwAuthenticatedBlobGateway({\n url,\n maxFetchBytes,\n mmAuth,\n ...fetchParams\n}: CreateKgwAuthenticatedBlobGatewayParams): BlobGateway {\n const storageAuth =\n mmAuth ?? (isMmTokenAuth(fetchParams.signer) ? fetchParams.signer : undefined);\n\n return new BlobGateway({\n url,\n maxFetchBytes,\n accessToken: storageAuth?.accessToken,\n fetchFn: createKgwAuthenticatedFetch(fetchParams),\n });\n}\n\nexport function createKgwAuthenticatedFetch({\n kwilClient,\n signer,\n fetchFn = fetch,\n isAuthFailure = defaultKgwAuthFailurePredicate,\n}: CreateKgwAuthenticatedFetchParams): typeof fetch {\n const nodeKwil = getNodeKwilClient(kwilClient);\n // Coalesce in-flight re-auths. Node isn't multi-threaded, but concurrent awaits still\n // interleave: two fetches can both see an auth failure and both call refreshCookie before\n // either finishes. Without this, that would kick off two authenticateKGWAndSetCookie calls.\n // See \"shares one refresh across parallel auth failures\".\n let refreshPromise: Promise<string> | undefined;\n\n const refreshCookie = async (): Promise<string> => {\n refreshPromise ??= nodeKwil.authenticateKGWAndSetCookie(signer).finally(() => {\n refreshPromise = undefined;\n });\n\n return refreshPromise;\n };\n\n const ensureCookie = async (): Promise<{ cookie: string; refreshed: boolean }> => {\n const existingCookie = nodeKwil.getKgwCookie();\n if (existingCookie) {\n return { cookie: existingCookie, refreshed: false };\n }\n\n return { cookie: await refreshCookie(), refreshed: true };\n };\n\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const { cookie } = await ensureCookie();\n const bufferedRequest = await bufferRequestBody(input, init);\n const response = await fetchFn(\n ...withCookie(input, withMaterializedBody(bufferedRequest), cookie),\n );\n\n const probe = authFailureProbe(response);\n if (!(await isAuthFailure(probe.response))) {\n return response;\n }\n\n // Discard the failed response so an unread body doesn't keep streaming.\n await discardUnreadBodies(probe.discardResponses);\n const refreshedCookie = await refreshCookie();\n return fetchFn(...withCookie(input, withMaterializedBody(bufferedRequest), refreshedCookie));\n };\n}\n\ntype AuthFailureProbe = {\n response: Response;\n discardResponses: Response[];\n};\n\n/**\n * Body is one-shot. Only clone when the default predicate might call `.json()`\n * (JSON content-type). Cloning a large blob response would tee the stream and\n * risk buffering the download on an abandoned branch — and in Node, canceling\n * that unread tee branch hangs.\n *\n * When a cloned response is thrown away after an auth failure, cancel both tee\n * branches together; canceling only one branch can wait forever for the other.\n */\nfunction authFailureProbe(response: Response): AuthFailureProbe {\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n const probe = response.clone();\n return { response: probe, discardResponses: [response, probe] };\n }\n\n return { response, discardResponses: [response] };\n}\n\nasync function discardUnreadBodies(responses: Response[]): Promise<void> {\n await Promise.all(responses.map(discardUnreadBody));\n}\n\nasync function discardUnreadBody(response: Response): Promise<void> {\n if (response.bodyUsed || !response.body) {\n return;\n }\n\n try {\n await response.body.cancel();\n } catch {\n // Already locked/closed by a concurrent reader.\n }\n}\n\ntype BufferedFormDataEntry =\n | { key: string; value: string }\n | { key: string; value: ArrayBuffer; fileName: string; type: string };\n\ntype BufferedBody =\n | { kind: \"body\"; value: BodyInit }\n | { kind: \"form-data\"; entries: BufferedFormDataEntry[] };\n\ntype BufferedRequestBody = {\n requestInit: RequestInit | undefined;\n bufferedBody?: BufferedBody;\n};\n\nasync function bufferRequestBody(\n input: RequestInfo | URL,\n init?: RequestInit,\n): Promise<BufferedRequestBody> {\n if (init?.body != null) {\n return {\n requestInit: init,\n bufferedBody: await bufferBody(init.body),\n };\n }\n\n if (input instanceof Request && input.body != null) {\n const requestClone = input.clone();\n return {\n requestInit: {\n ...init,\n method: init?.method ?? input.method,\n },\n bufferedBody: await bufferBody(requestClone.body!),\n };\n }\n\n return { requestInit: init };\n}\n\nfunction withMaterializedBody({\n requestInit,\n bufferedBody,\n}: BufferedRequestBody): RequestInit | undefined {\n if (!bufferedBody) {\n return requestInit;\n }\n\n return {\n ...requestInit,\n body: materializeBody(bufferedBody),\n };\n}\n\nasync function bufferBody(body: BodyInit): Promise<BufferedBody> {\n if (\n typeof body === \"string\" ||\n body instanceof Blob ||\n body instanceof ArrayBuffer ||\n body instanceof URLSearchParams\n ) {\n return { kind: \"body\", value: body };\n }\n\n if (ArrayBuffer.isView(body)) {\n return {\n kind: \"body\",\n value: new Uint8Array(body.buffer, body.byteOffset, body.byteLength),\n };\n }\n\n if (body instanceof FormData) {\n const entries: Promise<BufferedFormDataEntry>[] = [];\n\n body.forEach((value, key) => {\n entries.push(bufferFormDataEntry(key, value));\n });\n\n return { kind: \"form-data\", entries: await Promise.all(entries) };\n }\n\n if (body instanceof ReadableStream) {\n return {\n kind: \"body\",\n value: await new Response(body).arrayBuffer(),\n };\n }\n\n return { kind: \"body\", value: body };\n}\n\nasync function bufferFormDataEntry(\n key: string,\n value: FormDataEntryValue,\n): Promise<BufferedFormDataEntry> {\n if (typeof value === \"string\") {\n return { key, value };\n }\n\n return {\n key,\n value: await new Response(value).arrayBuffer(),\n fileName: value instanceof File ? value.name : \"blob\",\n type: value.type || \"application/octet-stream\",\n };\n}\n\nfunction materializeBody(bufferedBody: BufferedBody): BodyInit {\n if (bufferedBody.kind === \"body\") {\n return bufferedBody.value;\n }\n\n const formData = new FormData();\n\n for (const entry of bufferedBody.entries) {\n if (\"fileName\" in entry) {\n formData.append(entry.key, new Blob([entry.value], { type: entry.type }), entry.fileName);\n } else {\n formData.append(entry.key, entry.value);\n }\n }\n\n return formData;\n}\n\nfunction getNodeKwilClient(kwilClient: KwilActionClient): KgwSessionNodeKwil {\n if (!(kwilClient.client instanceof NodeKwil)) {\n throw new Error(\"KGW authenticated fetch can only be created from a NodeKwil client\");\n }\n\n if (!hasKgwSessionHelpers(kwilClient.client)) {\n throw new Error(\"NodeKwil client does not expose KGW session cookie helpers\");\n }\n\n return kwilClient.client;\n}\n\nfunction hasKgwSessionHelpers(client: NodeKwil): client is KgwSessionNodeKwil {\n const maybeClient = client as Partial<KgwSessionNodeKwil>;\n\n return (\n typeof maybeClient.getKgwCookie === \"function\" &&\n typeof maybeClient.authenticateKGWAndSetCookie === \"function\"\n );\n}\n\nfunction withCookie(\n input: RequestInfo | URL,\n init: RequestInit | undefined,\n cookie: string,\n): Parameters<typeof fetch> {\n const headers = new Headers(input instanceof Request ? input.headers : undefined);\n\n if (init?.headers) {\n new Headers(init.headers).forEach((value, key) => {\n headers.set(key, value);\n });\n }\n\n headers.set(\"Cookie\", cookie);\n\n return [input, { ...init, headers }];\n}\n\nasync function defaultKgwAuthFailurePredicate(response: Response): Promise<boolean> {\n if (response.status === 401) {\n return true;\n }\n\n const contentType = response.headers.get(\"content-type\");\n if (!contentType?.includes(\"application/json\")) {\n return false;\n }\n\n try {\n const body = (await response.json()) as { error?: { code?: number } };\n return body.error?.code === KGW_AUTH_ERROR_CODE;\n } catch {\n return false;\n }\n}\n","// Network configuration mapping\nconst NEAR_NETWORKS = {\n mainnet: {\n networkId: \"mainnet\",\n nodeUrl: \"https://rpc.mainnet.near.org\",\n },\n testnet: {\n networkId: \"testnet\",\n nodeUrl: \"https://rpc.testnet.near.org\",\n },\n betanet: {\n networkId: \"betanet\",\n nodeUrl: \"https://rpc.betanet.near.org\",\n },\n shardnet: {\n networkId: \"shardnet\",\n nodeUrl: \"https://rpc.shardnet.near.org\",\n },\n} as const;\n\n// Function to detect NEAR network from account ID\nexport const detectNearNetwork = (accountId: string): keyof typeof NEAR_NETWORKS => {\n if (accountId.endsWith(\".near\")) return \"mainnet\";\n if (accountId.endsWith(\".testnet\")) return \"testnet\";\n if (accountId.endsWith(\".betanet\")) return \"betanet\";\n if (accountId.endsWith(\".shardnet\")) return \"shardnet\";\n\n // Default to testnet for development, mainnet for production\n return \"testnet\";\n};\n\n// Function to get connection config based on account ID\nexport const getNearConnectionConfig = (\n accountId: string,\n): { networkId: string; nodeUrl: string } => {\n const network = detectNearNetwork(accountId);\n const networkConfig = NEAR_NETWORKS[network];\n\n return {\n networkId: networkConfig.networkId,\n nodeUrl: networkConfig.nodeUrl,\n };\n};\n","import type { Store } from \"@idos-network/utils/store\";\nimport type {\n Wallet as NearWallet,\n SignedMessage,\n SignMessageParams,\n} from \"@near-wallet-selector/core\";\nimport type { connect as connectT } from \"near-api-js\";\nimport type { AccessKeyList } from \"near-api-js/lib/providers/provider\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\nimport {\n base64Decode,\n binaryWriteUint16BE,\n bs58Decode,\n bytesConcat,\n hexEncode,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getNearConnectionConfig } from \"./get-config\";\nimport { nep413SignHash, serializeKwilNep413 } from \"./nep413\";\n\nconst NEAR_WALLET_TYPES: string[] = [\n \"browser\",\n \"injected\",\n \"instant-link\",\n \"hardware\",\n \"bridge\",\n] satisfies NearWallet[\"type\"][];\n\nexport function looksLikeNearWallet(signer: unknown): signer is NearWallet {\n return (\n signer !== null &&\n typeof signer === \"object\" &&\n \"id\" in signer &&\n \"metadata\" in signer &&\n \"type\" in signer &&\n typeof signer.type === \"string\" &&\n NEAR_WALLET_TYPES.includes(signer.type)\n );\n}\n\nclass KwilNonce {\n bytes: Uint8Array;\n\n constructor(length = 32) {\n // We're in the browser, so there's a window.crypto for sure.\n /* global crypto */\n this.bytes = crypto.getRandomValues(new Uint8Array(length));\n }\n\n get clampUTF8() {\n return this.bytes.map((byte) => byte & 127);\n }\n}\n\n/**\n * Creates a signer function that can be used to sign messages with a NEAR wallet\n */\nfunction createNearWalletSigner(\n wallet: NearWallet,\n recipient: string,\n): (message: string | Uint8Array) => Promise<Uint8Array> {\n return async (message: string | Uint8Array): Promise<Uint8Array> => {\n const messageString = typeof message === \"string\" ? message : utf8Decode(message);\n\n if (!wallet.signMessage) {\n throw new Error(\"Only wallets with signMessage are supported.\");\n }\n\n const nonceSuggestion = Buffer.from(new KwilNonce(32).bytes);\n\n const {\n nonce = nonceSuggestion,\n signature,\n // @ts-expect-error Signatures don't seem to be updated for NEP413 yet.\n callbackUrl,\n // oxlint-disable-next-line typescript/no-non-null-assertion -- Only non-signing wallets return void.\n } = (await (\n wallet.signMessage as (\n _: SignMessageParams,\n ) => Promise<SignedMessage & { nonce?: Uint8Array }>\n )({\n message: messageString,\n recipient,\n nonce: nonceSuggestion,\n }))!;\n\n const nep413BorshPayload = serializeKwilNep413({\n message: messageString,\n nonce: Array.from(nonce),\n recipient,\n callbackUrl,\n });\n const result = bytesConcat(\n binaryWriteUint16BE(nep413BorshPayload.length),\n nep413BorshPayload,\n base64Decode(signature),\n );\n\n return result;\n };\n}\n\nexport function implicitAddressFromPublicKey(publicKey: string): string {\n const key_without_prefix = publicKey.replace(/^ed25519:/, \"\");\n return hexEncode(bs58Decode(key_without_prefix), true);\n}\n\nexport async function getNearFullAccessPublicKeys(\n namedAddress: string,\n): Promise<string[] | undefined> {\n let connect: typeof connectT;\n try {\n connect = (await import(\"near-api-js\")).connect;\n } catch (_e) {\n throw new Error(\"Can't load near-api-js\");\n }\n const connectionConfig = getNearConnectionConfig(namedAddress);\n const nearConnection = await connect(connectionConfig);\n\n try {\n const response: AccessKeyList = await nearConnection.connection.provider.query({\n request_type: \"view_access_key_list\",\n finality: \"final\",\n account_id: namedAddress,\n });\n return response.keys\n .filter((element) => element.access_key.permission === \"FullAccess\")\n ?.map((i) => i.public_key);\n } catch {\n // `Near` failed if namedAddress contains uppercase symbols\n return;\n }\n}\n\ntype NearRedirect = {\n accountId?: string;\n publicKey?: string;\n signature?: string;\n error?: string;\n};\n\nfunction parseNearRedirect(hash: string): NearRedirect {\n const params = new URLSearchParams(hash.startsWith(\"#\") ? hash.slice(1) : hash);\n const signature = params.get(\"signature\");\n return {\n accountId: params.get(\"accountId\") ?? undefined,\n publicKey: params.get(\"publicKey\") ?? undefined,\n // URLSearchParams decodes a literal \"+\" as a space. NEP-413 signatures are base64.\n signature: signature?.replaceAll(\" \", \"+\"),\n error: params.get(\"error\") ?? undefined,\n };\n}\n\nfunction takeNearRedirect(): NearRedirect {\n const redirect = parseNearRedirect(window.location.hash);\n if (!redirect.accountId && !redirect.publicKey && !redirect.signature && !redirect.error) {\n return redirect;\n }\n\n const params = new URLSearchParams(window.location.hash.slice(1));\n for (const key of [\"accountId\", \"publicKey\", \"signature\", \"error\", \"state\"]) params.delete(key);\n const rest = params.toString();\n window.history.replaceState(\n null,\n \"\",\n `${window.location.pathname}${window.location.search}${rest ? `#${rest}` : \"\"}`,\n );\n return redirect;\n}\n\nfunction verifyNep413Signature(\n message: string,\n nonce: Uint8Array,\n recipient: string,\n callbackUrl: string,\n signature: string,\n publicKey: string,\n): boolean {\n const pieces = publicKey.split(\":\");\n if (pieces.length !== 2 || pieces[0] !== \"ed25519\" || !pieces[1] || nonce.length !== 32) {\n return false;\n }\n\n try {\n const publicKeyBytes = bs58Decode(pieces[1]);\n const signatureBytes = base64Decode(signature);\n if (publicKeyBytes.length !== 32 || signatureBytes.length !== 64) return false;\n\n return nacl.sign.detached.verify(\n nep413SignHash({ message, nonce, recipient, callbackUrl }),\n signatureBytes,\n publicKeyBytes,\n );\n } catch {\n return false;\n }\n}\n\n// The hash is attacker-controlled. A signature is only the wallet's if it verifies\n// against the request we stored before the redirect, for a full-access key of this account.\nasync function trustedNearRedirect(\n redirect: NearRedirect,\n currentAddress: string,\n recipient: string,\n store: Store,\n): Promise<{ signature: string; publicKey: string } | undefined> {\n if (\n redirect.error ||\n !redirect.signature ||\n !redirect.publicKey ||\n redirect.accountId !== currentAddress\n ) {\n return;\n }\n\n const message = await store.get<string>(\"sign-last-message\");\n const savedNonce = await store.get<number[] | Uint8Array>(\"sign-last-nonce\");\n const callbackUrl = await store.get<string>(\"sign-last-url\");\n if (!message || !savedNonce || !callbackUrl) return;\n\n const nonce = Uint8Array.from(savedNonce);\n if (\n !verifyNep413Signature(\n message,\n nonce,\n recipient,\n callbackUrl,\n redirect.signature,\n redirect.publicKey,\n )\n ) {\n return;\n }\n\n const keys = await getNearFullAccessPublicKeys(currentAddress);\n if (!keys?.includes(redirect.publicKey)) return;\n\n return { signature: redirect.signature, publicKey: redirect.publicKey };\n}\n\nexport async function signNearMessage(\n wallet: NearWallet,\n message: string,\n recipient = \"idos.network\",\n): Promise<string> {\n const signer = createNearWalletSigner(wallet, recipient);\n const signedPayload = await signer(message);\n return hexEncode(signedPayload);\n}\n\nexport async function createNearWalletKwilSigner(\n wallet: NearWallet,\n currentAddress: string,\n store: Store,\n kwilClient: KwilActionClient,\n recipient = \"idos.network\",\n): Promise<{ kwilSigner: KwilSigner; publicKey: string }> {\n if (!wallet.signMessage) throw new Error(\"Only wallets with signMessage are supported.\");\n\n if (wallet.id === \"my-near-wallet\") {\n const redirect = takeNearRedirect();\n const trusted = await trustedNearRedirect(redirect, currentAddress, recipient, store);\n\n if (trusted) {\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", trusted.publicKey);\n }\n\n const signMessageOriginal = wallet.signMessage.bind(wallet);\n\n wallet.signMessage = async ({\n message,\n recipient: signRecipient,\n }: SignMessageParams): Promise<SignedMessage & { nonce?: Uint8Array }> => {\n if (redirect.error) return Promise.reject();\n\n const lastMessage = await store.get<string>(\"sign-last-message\");\n const lastNonce = await store.get<Uint8Array>(\"sign-last-nonce\");\n\n if (trusted && message === lastMessage && lastNonce) {\n const nonce = Buffer.from(lastNonce);\n const callbackUrl = await store.get<string>(\"sign-last-url\");\n\n return Promise.resolve({\n accountId: currentAddress,\n publicKey: trusted.publicKey,\n signature: trusted.signature,\n nonce,\n message,\n callbackUrl,\n } as SignedMessage);\n }\n\n const callbackUrl = window.location.href;\n const nonce = Buffer.from(new KwilNonce(32).clampUTF8);\n\n await store.set(\"sign-last-message\", message);\n await store.set(\"sign-last-nonce\", Array.from(nonce));\n await store.set(\"sign-last-url\", callbackUrl);\n\n signMessageOriginal({ message, nonce, recipient: signRecipient, callbackUrl });\n\n return new Promise(() => ({}) as SignedMessage);\n };\n }\n\n const storedAddress = await store.get<string>(\"signer-address\");\n\n let publicKey = await store.get<string>(\"signer-public-key\");\n\n if (storedAddress !== currentAddress || !publicKey) {\n store.reset();\n // To avoid re-using the old signer's kgw cookie.\n // When kwil-js supports multi cookies, we can remove this.\n await kwilClient.client.auth.logoutKGW();\n\n const message = \"idOS authentication\";\n const nonce = Buffer.from(new KwilNonce(32).bytes);\n const signResult = await wallet.signMessage({ message, recipient, nonce });\n if (!signResult) throw new Error(\"signMessage returned no result\");\n ({ publicKey } = signResult);\n\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", publicKey);\n }\n\n const signer = createNearWalletSigner(wallet, recipient);\n\n return {\n kwilSigner: new KwilSigner(signer, implicitAddressFromPublicKey(publicKey), \"nep413\"),\n publicKey,\n };\n}\n","import type * as GemWallet from \"@gemwallet/api\";\nimport type { Store } from \"@idos-network/utils/store\";\nimport type { Xumm } from \"xumm\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getXrpTxHash } from \"./utils\";\n\nexport async function createXrpKwilSigner(\n wallet: Xumm | typeof GemWallet,\n currentAddress: string,\n store: Store,\n kwilClient: KwilActionClient,\n walletPublicKey: string,\n): Promise<KwilSigner> {\n const storedAddress = await store.get<string>(\"signer-address\");\n const storePublicKey = await store.get<string>(\"signer-public-key\");\n\n if (storedAddress !== currentAddress || (storePublicKey && storePublicKey !== walletPublicKey)) {\n try {\n // HEADS UP: for some reason logoutKGW fails on xrp\n // storePublicKey && await kwilClient.client.auth.logoutKGW();\n console.log(\"logoutKGW\", kwilClient);\n } catch (error) {\n console.error(\"Failed to logout KGW:\", error);\n }\n }\n\n await store.set(\"signer-address\", currentAddress);\n await store.set(\"signer-public-key\", walletPublicKey);\n\n const signer = async (message: string | Uint8Array): Promise<Uint8Array> => {\n const signature = await getXrpTxHash(message, wallet);\n // Buffer.from(_, \"hex\") silently truncates at the first non-hex char, so reject it up front.\n if (!signature || !/^(?:[0-9a-f]{2})+$/i.test(signature)) {\n throw new Error(\"Failed to sign transaction with XRP\");\n }\n return Buffer.from(signature, \"hex\");\n };\n\n return new KwilSigner(signer, walletPublicKey, \"xrpl\");\n}\n","import type { Store } from \"@idos-network/utils/store\";\nimport type { Wallet as NearWallet } from \"@near-wallet-selector/core\";\nimport type { Keypair as StellarKeypair } from \"@stellar/stellar-sdk\";\nimport type { Wallet as EthersWallet, JsonRpcSigner } from \"ethers\";\nimport type { KeyPair as NearKeyPair } from \"near-api-js\";\nimport type { KeyPair as XrpKeyPair } from \"ripple-keypairs/src/types\";\n\nimport { KwilSigner } from \"@idos-network/kwil-js\";\nimport { base64UrlEncode, bs58Encode, hexDecode, hexEncode } from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nimport type { WalletType } from \"./actions\";\nimport type { KwilActionClient } from \"./create-kwil-client\";\nimport type { MmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\n\nimport { FaceSignSignerProvider } from \"./facesign/facesign-signer\";\nimport { isMmTokenAuth } from \"./mm-token/create-mm-token-kwil-signer\";\nimport {\n createNearWalletKwilSigner,\n implicitAddressFromPublicKey,\n looksLikeNearWallet,\n} from \"./near/create-near-wallet-kwil-signer\";\nimport { kwilNep413Signer } from \"./near/nep413\";\nimport { createXrpKwilSigner } from \"./xrp/signer\";\nimport { getXrpPublicKey, looksLikeXrpWallet } from \"./xrp/utils\";\n\nexport { KwilSigner } from \"@idos-network/kwil-js\";\nexport type Wallet =\n | EthersWallet\n | JsonRpcSigner\n | NearWallet\n | CustomKwilSigner\n | MmTokenAuth\n | FaceSignSignerProvider;\n\n/**\n * Helper function to check if the given object is a `nacl.SignKeyPair`.\n */\nfunction isNaclSignKeyPair(object: unknown): object is nacl.SignKeyPair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicKey\" in object &&\n object.publicKey instanceof Uint8Array &&\n object.publicKey.length === nacl.sign.publicKeyLength &&\n \"secretKey\" in object &&\n object.secretKey instanceof Uint8Array &&\n object.secretKey.length === nacl.sign.secretKeyLength\n );\n}\n\n/**\n * Helper function to check if the given object is a NEAR KeyPair.\n */\nfunction isNearKeyPair(object: unknown): object is NearKeyPair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"getPublicKey\" in object &&\n \"sign\" in object &&\n typeof object.getPublicKey === \"function\" &&\n typeof object.sign === \"function\"\n );\n}\n\n/**\n * Helper function to check if the given object is a Stellar Keypair.\n */\nfunction isStellarKeyPair(object: unknown): object is StellarKeypair {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicKey\" in object &&\n \"sign\" in object &&\n \"canSign\" in object &&\n typeof object.publicKey === \"function\" &&\n typeof object.sign === \"function\" &&\n typeof object.canSign === \"function\"\n );\n}\n\nexport interface CustomKwilSigner extends KwilSigner {\n publicAddress: string;\n signatureType: string;\n publicKey: string;\n walletType: string;\n signMessage: (message: Uint8Array | string) => Promise<Uint8Array>;\n}\n\nfunction isCustomKwilSigner(object: unknown): object is CustomKwilSigner {\n return (\n object !== null &&\n typeof object === \"object\" &&\n \"publicAddress\" in object &&\n \"signatureType\" in object &&\n \"publicKey\" in object &&\n \"signMessage\" in object\n );\n}\n\n/**\n * Helper function to check if the given object is a XRP KeyPair (Server key pairs only).\n */\nfunction isXrplKeyPair(object: unknown): object is XrpKeyPair {\n return !!object && typeof object === \"object\" && \"privateKey\" in object && \"publicKey\" in object;\n}\n\nexport type KwilSignerType =\n | NearKeyPair\n | EthersWallet\n | nacl.SignKeyPair\n | JsonRpcSigner\n | StellarKeypair\n | XrpKeyPair\n | MmTokenAuth;\n\nexport type SignerAddress = string;\nexport type SignerPublicKey = string | undefined;\n\n/**\n * Creates a `KwilSigner` and its associated `SignerAddress`.\n *\n * This function is explicitly marked as being for backend use only because it doesn't reset\n * the KGW cookie when logging out and re-logging in with a different wallet.\n */\nexport async function createServerKwilSigner(\n signer: KwilSignerType,\n): Promise<[KwilSigner, SignerAddress]> {\n if (isMmTokenAuth(signer)) {\n return [signer, base64UrlEncode(signer.identifier)];\n }\n\n if (isNaclSignKeyPair(signer)) {\n return [\n new KwilSigner(\n async (msg: Uint8Array) => nacl.sign.detached(msg, signer.secretKey),\n signer.publicKey,\n \"ed25519\",\n ),\n implicitAddressFromPublicKey(bs58Encode(signer.publicKey)),\n ];\n }\n\n if (isNearKeyPair(signer)) {\n const rawPublicKey = signer.getPublicKey().toString();\n const hexPublicKey = implicitAddressFromPublicKey(rawPublicKey);\n return [\n new KwilSigner(kwilNep413Signer(\"idos-issuer\")(signer), hexPublicKey, \"nep413\"),\n rawPublicKey,\n ];\n }\n\n if (isStellarKeyPair(signer)) {\n const publicKeyString = signer.publicKey();\n const rawPublicKey = signer.rawPublicKey();\n return [\n new KwilSigner(\n async (msg: Uint8Array) => signer.sign(Buffer.from(msg)),\n rawPublicKey,\n \"ed25519\",\n ),\n publicKeyString,\n ];\n }\n\n if (isXrplKeyPair(signer)) {\n let xrpKeypair: typeof import(\"ripple-keypairs\");\n\n try {\n xrpKeypair = await import(\"ripple-keypairs\");\n } catch (e) {\n throw new Error(\"Can't load ripple-keypairs\", { cause: e });\n }\n\n return [\n new KwilSigner(\n async (msg: Uint8Array) => hexDecode(xrpKeypair.sign(hexEncode(msg), signer.privateKey)),\n signer.publicKey,\n \"xrpl\",\n ),\n signer.publicKey,\n ];\n }\n\n if (\"address\" in signer) {\n return [new KwilSigner(signer, signer.address), signer.address];\n }\n\n // Force the check that `signer` is never.\n // If these lines start complaining, that means we're missing an `if` above.\n return ((_: never) => {\n throw new Error(\"Invalid `signer` type\");\n })(signer);\n}\n\nexport async function createClientKwilSigner(\n store: Store,\n kwilClient: KwilActionClient,\n wallet: Wallet,\n): Promise<[KwilSigner, SignerAddress, SignerPublicKey, WalletType]> {\n if (\"connect\" in wallet && \"address\" in wallet) {\n // oxlint-disable-next-line no-param-reassign -- Narrowing the type on purpose\n wallet = wallet as unknown as JsonRpcSigner;\n const currentAddress = await wallet.getAddress();\n\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== currentAddress) {\n // To avoid re-using the old signer's kgw cookie.\n // When kwil-js supports multi cookies, we can remove this.\n store.set(\"signer-address\", currentAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [new KwilSigner(wallet, currentAddress), currentAddress, undefined, \"EVM\"];\n }\n\n if (looksLikeNearWallet(wallet)) {\n const accounts = await wallet.getAccounts();\n const { kwilSigner, publicKey } = await createNearWalletKwilSigner(\n wallet,\n accounts[0].accountId,\n store,\n kwilClient,\n );\n\n return [kwilSigner, accounts[0].accountId, publicKey, \"NEAR\"];\n }\n\n if (looksLikeXrpWallet(wallet)) {\n const { address: currentAddress, publicKey: walletPublicKey } = (await getXrpPublicKey(\n wallet,\n )) as { address: string; publicKey: string };\n if (!currentAddress) {\n throw new Error(\"Failed to get XRP address\");\n }\n\n return [\n await createXrpKwilSigner(wallet, currentAddress, store, kwilClient, walletPublicKey),\n currentAddress,\n walletPublicKey,\n \"XRPL\",\n ];\n }\n\n if (isMmTokenAuth(wallet)) {\n const currentAddress = base64UrlEncode(wallet.identifier);\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== currentAddress) {\n // A different MM signing identity must not re-use the previous KGW cookie.\n store.set(\"signer-address\", currentAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [wallet, currentAddress, currentAddress, \"MM\"];\n }\n\n if (isCustomKwilSigner(wallet) || wallet instanceof FaceSignSignerProvider) {\n const storedAddress = await store.get<string>(\"signer-address\");\n\n if (storedAddress !== wallet.publicAddress) {\n store.set(\"signer-address\", wallet.publicAddress);\n try {\n await kwilClient.client.auth.logoutKGW();\n } catch (error) {\n console.log(\"error logoutKGW\", error);\n }\n }\n\n return [\n new KwilSigner(\n async (msg: Uint8Array) => wallet.signMessage(msg),\n wallet.publicAddress,\n \"ed25519\",\n ),\n wallet.publicAddress,\n wallet.publicKey,\n wallet.walletType as WalletType,\n ];\n }\n\n // Force the check that `signer` is `never`.\n // If these lines start complaining, that means we're missing an `if` above.\n return ((_: never) => {\n throw new Error(\"Invalid `signer` type\");\n })(wallet);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { Ln as WalletType } from "../index-Bk8YCFlx.mjs";
1
+ import { Un as WalletType } from "../index-Dwonqvwu.mjs";
2
2
  //#region src/signature-verification/index.d.ts
3
3
  export interface WalletSignature {
4
4
  address: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idos-network/kwil-infra",
3
- "version": "3.0.1",
3
+ "version": "4.0.0",
4
4
  "description": "Infrastructure and wallets for idOS",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@idos-network/kwil-js": "0.2.2",
47
- "@idos-network/utils": "3.0.1",
47
+ "@idos-network/utils": "3.1.0",
48
48
  "tiny-invariant": "^1.3.3",
49
49
  "tweetnacl": "^1.0.3",
50
50
  "zod": "4.6.7"
@@ -3,6 +3,7 @@ import { describe, expect, it } from "vitest";
3
3
  import {
4
4
  addWalletMessage,
5
5
  CreatePreliminaryCredentialsByDwgInputSchema,
6
+ credentialBroaderMessage,
6
7
  getUser,
7
8
  SharePreliminaryCredentialInputSchema,
8
9
  UpsertWalletAsInserterInputSchema,
@@ -151,8 +152,8 @@ describe("MM wallet type schemas", () => {
151
152
  });
152
153
 
153
154
  const addWalletMessageInput = {
154
- address: "mm-signing-public-key",
155
- wallet_type: "MM" as const,
155
+ address: "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed",
156
+ wallet_type: "EVM" as const,
156
157
  user_id: "00000000-0000-4000-8000-000000000001",
157
158
  not_before: "2025-02-13T11:22:06Z",
158
159
  not_after: "2025-02-13T11:37:06Z",
@@ -178,6 +179,21 @@ describe("addWalletMessage", () => {
178
179
  });
179
180
  });
180
181
 
182
+ describe("credentialBroaderMessage", () => {
183
+ it("returns the message from the node", async () => {
184
+ await expect(
185
+ credentialBroaderMessage(
186
+ { call: async () => [{ message: "operation: credential" }] } as never,
187
+ {
188
+ public_notes_signature: "sig",
189
+ content_uri: "ipfs://cid",
190
+ recipient_wallet: "0xabc",
191
+ },
192
+ ),
193
+ ).resolves.toEqual({ message: "operation: credential" });
194
+ });
195
+ });
196
+
181
197
  describe("getUser", () => {
182
198
  it("throws an explicit not-found error when the view is empty", async () => {
183
199
  await expect(
@@ -12,6 +12,11 @@ export const WALLET_TYPES = ["EVM", "NEAR", "XRPL", "Stellar", "FaceSign", "MM"]
12
12
  export type WalletType = (typeof WALLET_TYPES)[number];
13
13
 
14
14
  export const walletTypeSchema: z.ZodType<WalletType> = z.enum(WALLET_TYPES);
15
+ export const ADD_WALLET_TYPES = ["EVM", "NEAR", "XRPL", "Stellar", "FaceSign"] as const;
16
+
17
+ export type AddWalletType = (typeof ADD_WALLET_TYPES)[number];
18
+
19
+ export const addWalletTypeSchema: z.ZodType<AddWalletType> = z.enum(ADD_WALLET_TYPES);
15
20
  export const ENCRYPTION_PASSWORD_STORES = ["user", "mpc", "mm"] as const;
16
21
 
17
22
  export type EncryptionPasswordStore = (typeof ENCRYPTION_PASSWORD_STORES)[number];
@@ -165,6 +170,20 @@ export const actionSchema: Record<string, ActionSchemaElement[]> = {
165
170
  type: DataType.Uuid,
166
171
  },
167
172
  ],
173
+ credential_broader_message: [
174
+ {
175
+ name: "public_notes_signature",
176
+ type: DataType.Text,
177
+ },
178
+ {
179
+ name: "content_uri",
180
+ type: DataType.Text,
181
+ },
182
+ {
183
+ name: "recipient_wallet",
184
+ type: DataType.Text,
185
+ },
186
+ ],
168
187
  create_preliminary_credential: [
169
188
  {
170
189
  name: "request_id",
@@ -736,7 +755,7 @@ export type GetUserAsInserterOutput = z.infer<typeof GetUserAsInserterOutputSche
736
755
  export async function getUserAsInserter(
737
756
  kwilClient: KwilActionClient,
738
757
  params: GetUserAsInserterInput,
739
- ): Promise<GetUserAsInserterOutput> {
758
+ ): Promise<GetUserAsInserterOutput | undefined> {
740
759
  const inputs = GetUserAsInserterInputSchema.parse(params);
741
760
  return await kwilClient
742
761
  .call<GetUserAsInserterOutput[]>({
@@ -792,13 +811,13 @@ export async function upsertWalletAsInserter(
792
811
 
793
812
  export const AddWalletMessageInputSchema: z.ZodObject<{
794
813
  address: z.ZodString;
795
- wallet_type: z.ZodType<WalletType>;
814
+ wallet_type: z.ZodType<AddWalletType>;
796
815
  user_id: z.ZodUUID;
797
816
  not_before: z.ZodISODateTime;
798
817
  not_after: z.ZodISODateTime;
799
818
  }> = z.object({
800
819
  address: z.string(),
801
- wallet_type: walletTypeSchema,
820
+ wallet_type: addWalletTypeSchema,
802
821
  user_id: z.uuid(),
803
822
  not_before: rfc3339DateTimeSchema,
804
823
  not_after: rfc3339DateTimeSchema,
@@ -834,7 +853,7 @@ export const AddWalletInputSchema: z.ZodObject<{
834
853
  id: z.ZodUUID;
835
854
  address: z.ZodString;
836
855
  public_key: z.ZodOptional<z.ZodNullable<z.ZodString>>;
837
- wallet_type: z.ZodType<WalletType>;
856
+ wallet_type: z.ZodType<AddWalletType>;
838
857
  not_before: z.ZodISODateTime;
839
858
  not_after: z.ZodISODateTime;
840
859
  signature: z.ZodString;
@@ -842,7 +861,7 @@ export const AddWalletInputSchema: z.ZodObject<{
842
861
  id: z.uuid(),
843
862
  address: z.string(),
844
863
  public_key: z.string().nullish(),
845
- wallet_type: walletTypeSchema,
864
+ wallet_type: addWalletTypeSchema,
846
865
  not_before: rfc3339DateTimeSchema,
847
866
  not_after: rfc3339DateTimeSchema,
848
867
  signature: z.string(),
@@ -868,7 +887,7 @@ export const GetWalletsOutputSchema: z.ZodObject<{
868
887
  address: z.ZodString;
869
888
  public_key: z.ZodNullable<z.ZodString>;
870
889
  wallet_type: z.ZodType<WalletType>;
871
- message: z.ZodString;
890
+ message: z.ZodNullable<z.ZodString>;
872
891
  signature: z.ZodString;
873
892
  inserter: z.ZodNullable<z.ZodString>;
874
893
  }> = z.object({
@@ -877,7 +896,7 @@ export const GetWalletsOutputSchema: z.ZodObject<{
877
896
  address: z.string(),
878
897
  public_key: z.string().nullable(),
879
898
  wallet_type: walletTypeSchema,
880
- message: z.string(),
899
+ message: z.string().nullable(),
881
900
  signature: z.string(),
882
901
  inserter: z.string().nullable(),
883
902
  });
@@ -911,6 +930,43 @@ export async function removeWallet(
911
930
  });
912
931
  }
913
932
 
933
+ export const CredentialBroaderMessageInputSchema: z.ZodObject<{
934
+ public_notes_signature: z.ZodString;
935
+ content_uri: z.ZodString;
936
+ recipient_wallet: z.ZodString;
937
+ }> = z.object({
938
+ public_notes_signature: z.string(),
939
+ content_uri: blobContentUriSchema,
940
+ recipient_wallet: z.string(),
941
+ });
942
+
943
+ export type CredentialBroaderMessageInput = z.infer<typeof CredentialBroaderMessageInputSchema>;
944
+
945
+ export const CredentialBroaderMessageOutputSchema: z.ZodObject<{
946
+ message: z.ZodString;
947
+ }> = z.object({
948
+ message: z.string(),
949
+ });
950
+
951
+ export type CredentialBroaderMessageOutput = z.infer<typeof CredentialBroaderMessageOutputSchema>;
952
+
953
+ /** CREDENTIAL ACTIONS */
954
+ export async function credentialBroaderMessage(
955
+ kwilClient: KwilActionClient,
956
+ params: CredentialBroaderMessageInput,
957
+ ): Promise<CredentialBroaderMessageOutput> {
958
+ const inputs = CredentialBroaderMessageInputSchema.parse(params);
959
+ return await kwilClient
960
+ .call<CredentialBroaderMessageOutput[]>({
961
+ name: "credential_broader_message",
962
+ inputs,
963
+ })
964
+ .then((result) => {
965
+ if (!result[0]) throw new Error("credential_broader_message returned no rows");
966
+ return result[0];
967
+ });
968
+ }
969
+
914
970
  export const CreatePreliminaryCredentialInputSchema: z.ZodObject<{
915
971
  request_id: z.ZodUUID;
916
972
  credential_id: z.ZodUUID;
@@ -939,7 +995,6 @@ export type CreatePreliminaryCredentialInput = z.infer<
939
995
  typeof CreatePreliminaryCredentialInputSchema
940
996
  >;
941
997
 
942
- /** CREDENTIAL ACTIONS */
943
998
  export async function createPreliminaryCredential(
944
999
  kwilClient: KwilActionClient,
945
1000
  params: CreatePreliminaryCredentialInput,
@@ -1260,7 +1315,7 @@ export type CredentialExistAsInserterOutput = z.infer<typeof CredentialExistAsIn
1260
1315
  export async function credentialExistAsInserter(
1261
1316
  kwilClient: KwilActionClient,
1262
1317
  params: CredentialExistAsInserterInput,
1263
- ): Promise<CredentialExistAsInserterOutput> {
1318
+ ): Promise<CredentialExistAsInserterOutput | undefined> {
1264
1319
  const inputs = CredentialExistAsInserterInputSchema.parse(params);
1265
1320
  return await kwilClient
1266
1321
  .call<CredentialExistAsInserterOutput[]>({
@@ -1380,7 +1435,7 @@ export type GetSiblingCredentialIdOutput = z.infer<typeof GetSiblingCredentialId
1380
1435
  export async function getSiblingCredentialId(
1381
1436
  kwilClient: KwilActionClient,
1382
1437
  params: GetSiblingCredentialIdInput,
1383
- ): Promise<GetSiblingCredentialIdOutput> {
1438
+ ): Promise<GetSiblingCredentialIdOutput | undefined> {
1384
1439
  const inputs = GetSiblingCredentialIdInputSchema.parse(params);
1385
1440
  return await kwilClient
1386
1441
  .call<GetSiblingCredentialIdOutput[]>({
@@ -1573,7 +1628,7 @@ export type DwgMessageOutput = z.infer<typeof DwgMessageOutputSchema>;
1573
1628
  export async function dwgMessage(
1574
1629
  kwilClient: KwilActionClient,
1575
1630
  params: DwgMessageInput,
1576
- ): Promise<DwgMessageOutput> {
1631
+ ): Promise<DwgMessageOutput | undefined> {
1577
1632
  const inputs = DwgMessageInputSchema.parse(params);
1578
1633
  return await kwilClient
1579
1634
  .call<DwgMessageOutput[]>({
@@ -1708,7 +1763,7 @@ export type GetAccessGrantsGrantedCountOutput = z.infer<
1708
1763
  export async function getAccessGrantsGrantedCount(
1709
1764
  kwilClient: KwilActionClient,
1710
1765
  params: GetAccessGrantsGrantedCountInput,
1711
- ): Promise<GetAccessGrantsGrantedCountOutput> {
1766
+ ): Promise<GetAccessGrantsGrantedCountOutput | undefined> {
1712
1767
  const inputs = GetAccessGrantsGrantedCountInputSchema.parse(params);
1713
1768
  return await kwilClient
1714
1769
  .call<GetAccessGrantsGrantedCountOutput[]>({
@@ -1737,7 +1792,7 @@ export type HasLockedAccessGrantsOutput = z.infer<typeof HasLockedAccessGrantsOu
1737
1792
  export async function hasLockedAccessGrants(
1738
1793
  kwilClient: KwilActionClient,
1739
1794
  params: HasLockedAccessGrantsInput,
1740
- ): Promise<HasLockedAccessGrantsOutput> {
1795
+ ): Promise<HasLockedAccessGrantsOutput | undefined> {
1741
1796
  const inputs = HasLockedAccessGrantsInputSchema.parse(params);
1742
1797
  return await kwilClient
1743
1798
  .call<HasLockedAccessGrantsOutput[]>({
@@ -1815,7 +1870,7 @@ export type HasProfileOutput = z.infer<typeof HasProfileOutputSchema>;
1815
1870
  export async function hasProfile(
1816
1871
  kwilClient: KwilActionClient,
1817
1872
  params: HasProfileInput,
1818
- ): Promise<HasProfileOutput> {
1873
+ ): Promise<HasProfileOutput | undefined> {
1819
1874
  const inputs = HasProfileInputSchema.parse(params);
1820
1875
  return await kwilClient
1821
1876
  .call<HasProfileOutput[]>(
@@ -1867,7 +1922,7 @@ export type CheckCallerPayerOutput = z.infer<typeof CheckCallerPayerOutputSchema
1867
1922
  export async function checkCallerPayer(
1868
1923
  kwilClient: KwilActionClient,
1869
1924
  params: CheckCallerPayerInput,
1870
- ): Promise<CheckCallerPayerOutput> {
1925
+ ): Promise<CheckCallerPayerOutput | undefined> {
1871
1926
  const inputs = CheckCallerPayerInputSchema.parse(params);
1872
1927
  return await kwilClient
1873
1928
  .call<CheckCallerPayerOutput[]>({
@@ -1918,7 +1973,7 @@ export type CheckBalanceOutput = z.infer<typeof CheckBalanceOutputSchema>;
1918
1973
  export async function checkBalance(
1919
1974
  kwilClient: KwilActionClient,
1920
1975
  params: CheckBalanceInput,
1921
- ): Promise<CheckBalanceOutput> {
1976
+ ): Promise<CheckBalanceOutput | undefined> {
1922
1977
  const inputs = CheckBalanceInputSchema.parse(params);
1923
1978
  return await kwilClient
1924
1979
  .call<CheckBalanceOutput[]>({
@@ -1949,7 +2004,7 @@ export type GetWalletWithBalanceOutput = z.infer<typeof GetWalletWithBalanceOutp
1949
2004
  export async function getWalletWithBalance(
1950
2005
  kwilClient: KwilActionClient,
1951
2006
  params: GetWalletWithBalanceInput,
1952
- ): Promise<GetWalletWithBalanceOutput> {
2007
+ ): Promise<GetWalletWithBalanceOutput | undefined> {
1953
2008
  const inputs = GetWalletWithBalanceInputSchema.parse(params);
1954
2009
  return await kwilClient
1955
2010
  .call<GetWalletWithBalanceOutput[]>({
@@ -1989,7 +2044,9 @@ export const GetAllowanceOutputSchema: z.ZodObject<{
1989
2044
  export type GetAllowanceOutput = z.infer<typeof GetAllowanceOutputSchema>;
1990
2045
 
1991
2046
  /** FaceSign should not be able to call this */
1992
- export async function getAllowance(kwilClient: KwilActionClient): Promise<GetAllowanceOutput> {
2047
+ export async function getAllowance(
2048
+ kwilClient: KwilActionClient,
2049
+ ): Promise<GetAllowanceOutput | undefined> {
1993
2050
  return await kwilClient
1994
2051
  .call<GetAllowanceOutput[]>({
1995
2052
  name: "get_allowance",
@@ -2045,7 +2102,7 @@ export type GetIssuerFeeOutput = z.infer<typeof GetIssuerFeeOutputSchema>;
2045
2102
  export async function getIssuerFee(
2046
2103
  kwilClient: KwilActionClient,
2047
2104
  params: GetIssuerFeeInput,
2048
- ): Promise<GetIssuerFeeOutput> {
2105
+ ): Promise<GetIssuerFeeOutput | undefined> {
2049
2106
  const inputs = GetIssuerFeeInputSchema.parse(params);
2050
2107
  return await kwilClient
2051
2108
  .call<GetIssuerFeeOutput[]>({