@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.
- package/CHANGELOG.md +17 -0
- package/dist/actions/index.d.mts +2 -2
- package/dist/actions/index.mjs +1 -1
- package/dist/actions/index.mjs.map +1 -1
- package/dist/{index-Bk8YCFlx.d.mts → index-Dwonqvwu.d.mts} +32 -19
- package/dist/index-Dwonqvwu.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/signature-verification/index.d.mts +1 -1
- package/package.json +2 -2
- package/src/actions/actions.test.ts +18 -2
- package/src/actions/actions.ts +76 -19
- package/src/mm-token/create-mm-token-kwil-signer.test.ts +0 -16
- package/src/mm-token/create-mm-token-kwil-signer.ts +0 -5
- package/dist/index-Bk8YCFlx.d.mts.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -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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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idos-network/kwil-infra",
|
|
3
|
-
"version": "
|
|
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
|
|
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: "
|
|
155
|
-
wallet_type: "
|
|
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(
|
package/src/actions/actions.ts
CHANGED
|
@@ -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<
|
|
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:
|
|
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<
|
|
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:
|
|
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(
|
|
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[]>({
|