@idos-network/kwil-infra 1.5.0 → 2.2.2
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 +73 -0
- package/README.md +46 -1
- package/dist/actions/index.d.mts +2 -2
- package/dist/actions/index.mjs +1 -1370
- package/dist/actions/index.mjs.map +1 -1
- package/dist/facesign/index.d.mts +1 -1
- package/dist/facesign/index.mjs +1 -2
- package/dist/{facesign-signer-BC24j1eN.d.mts → facesign-signer-5I8juA7p.d.mts} +2 -1
- package/dist/facesign-signer-5I8juA7p.d.mts.map +1 -0
- package/dist/facesign-signer-z5T312uQ.mjs +2 -0
- package/dist/facesign-signer-z5T312uQ.mjs.map +1 -0
- package/dist/{index-iqkJfgWf.d.mts → index-Bqz6trCk.d.mts} +223 -136
- package/dist/index-Bqz6trCk.d.mts.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +1 -429
- package/dist/index.mjs.map +1 -1
- package/dist/signature-verification/index.d.mts +3 -4
- package/dist/signature-verification/index.d.mts.map +1 -1
- package/dist/signature-verification/index.mjs +1 -134
- package/dist/signature-verification/index.mjs.map +1 -1
- package/dist/xrp/utils.d.mts +130 -20
- package/dist/xrp/utils.d.mts.map +1 -1
- package/dist/xrp/utils.mjs +1 -104
- package/dist/xrp/utils.mjs.map +1 -1
- package/dist/xrpl-credentials/index.d.mts +6 -7
- package/dist/xrpl-credentials/index.d.mts.map +1 -1
- package/dist/xrpl-credentials/index.mjs +1 -223
- package/dist/xrpl-credentials/index.mjs.map +1 -1
- package/package.json +9 -8
- package/src/actions/actions.test.ts +189 -0
- package/src/actions/actions.ts +368 -467
- package/src/actions/index.ts +38 -0
- package/src/create-kgw-authenticated-fetch.test.ts +377 -0
- package/src/create-kgw-authenticated-fetch.ts +321 -0
- package/src/create-kwil-client.ts +33 -10
- package/src/create-kwil-signer.test.ts +80 -0
- package/src/create-kwil-signer.ts +31 -5
- package/src/facesign/facesign-signer.test.ts +77 -0
- package/src/facesign/facesign-signer.ts +50 -2
- package/src/index.ts +2 -0
- package/src/mm-token/create-mm-token-kwil-signer.test.ts +148 -0
- package/src/mm-token/create-mm-token-kwil-signer.ts +166 -0
- package/src/near/create-near-wallet-kwil-signer.ts +1 -1
- package/src/signature-verification/index.test.ts +18 -0
- package/src/signature-verification/index.ts +7 -1
- package/src/wait-for-kwil-tx.test.ts +92 -0
- package/src/wait-for-kwil-tx.ts +111 -0
- package/src/xrp/signer.ts +2 -1
- package/src/xrp/utils.ts +7 -25
- package/tsdown.config.ts +1 -0
- package/dist/facesign-signer-BC24j1eN.d.mts.map +0 -1
- package/dist/facesign-signer-qzCcwunk.mjs +0 -244
- package/dist/facesign-signer-qzCcwunk.mjs.map +0 -1
- package/dist/index-iqkJfgWf.d.mts.map +0 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["#createActionInputs","#actionTypes","KwilSigner","KwilSigner","KwilSigner"],"sources":["../src/create-kwil-client.ts","../src/near/get-config.ts","../src/near/create-near-wallet-kwil-signer.ts","../src/near/nep413.ts","../src/xrp/signer.ts","../src/create-kwil-signer.ts"],"sourcesContent":["import type { Config } from \"@idos-network/kwil-js/dist/api_client/config\";\nimport type {\n ActionBody,\n CallBody,\n PositionalParams,\n} from \"@idos-network/kwil-js/dist/core/action\";\nimport type { DataInfo } from \"@idos-network/kwil-js/dist/core/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\";\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 async execute(\n params: KwilExecuteActionRequestParams,\n signer: KwilSigner | undefined = this.signer,\n synchronous = true,\n ): Promise<string | undefined> {\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, synchronous);\n return response.data?.tx_hash;\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","// 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 borshSerialize,\n bs58Decode,\n bytesConcat,\n hexEncode,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getNearConnectionConfig } from \"./get-config\";\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 nep413BorschSchema = {\n struct: {\n tag: \"u32\",\n message: \"string\",\n nonce: { array: { type: \"u8\", len: 32 } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n };\n\n const nep413BorshParams = {\n tag: 2147484061,\n message: messageString,\n nonce: Array.from(nonce),\n recipient,\n callbackUrl,\n };\n\n const nep413BorshPayload = borshSerialize(nep413BorschSchema, nep413BorshParams);\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));\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\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 { accountId, signature, publicKey, error } = Object.fromEntries(\n new URLSearchParams(window.location.hash.slice(1)).entries(),\n );\n\n if (signature) {\n await store.set(\"signer-address\", accountId);\n await store.set(\"signer-public-key\", publicKey);\n }\n\n const signMessageOriginal = wallet.signMessage.bind(wallet);\n\n wallet.signMessage = async ({\n message,\n recipient,\n }: SignMessageParams): Promise<SignedMessage & { nonce?: Uint8Array }> => {\n if (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 (signature && 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,\n 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, 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 { KeyPair } from \"near-api-js\";\n\nimport {\n binaryWriteUint16BE,\n borshSerialize,\n bytesConcat,\n sha256Hash,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\n\nexport function kwilNep413Signer(\n recipient: string,\n): (keyPair: KeyPair) => (messageBytes: Uint8Array) => Promise<Uint8Array> {\n return (keyPair: KeyPair) =>\n async (messageBytes: Uint8Array): Promise<Uint8Array> => {\n const message = utf8Decode(messageBytes);\n const nonceLength = 32;\n const nonce = crypto.getRandomValues(new Uint8Array(nonceLength));\n\n const nep413BorschSchema = {\n struct: {\n message: \"string\",\n nonce: { array: { type: \"u8\", len: nonceLength } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n } as const;\n\n const tag = 2147484061; // 2**31 + 413\n\n const { signature } = keyPair.sign(\n sha256Hash(\n bytesConcat(\n borshSerialize(\"u32\", tag),\n borshSerialize(nep413BorschSchema, { message, nonce, recipient }),\n ),\n ),\n );\n\n const kwilNep413BorschSchema = {\n struct: {\n tag: \"u32\",\n ...nep413BorschSchema.struct,\n },\n };\n\n const kwilNep413BorshParams = {\n tag,\n message,\n nonce,\n recipient,\n };\n\n const kwilNep413BorshPayload = borshSerialize(kwilNep413BorschSchema, kwilNep413BorshParams);\n\n return bytesConcat(\n binaryWriteUint16BE(kwilNep413BorshPayload.length),\n kwilNep413BorshPayload,\n signature,\n );\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 if (!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 { 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\";\n\nimport { FaceSignSignerProvider } from \"./facesign/facesign-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 | 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\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 (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 publicKey = implicitAddressFromPublicKey(signer.getPublicKey().toString());\n return [\n new KwilSigner(kwilNep413Signer(\"idos-issuer\")(signer), publicKey, \"nep413\"),\n publicKey,\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 (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/near/nep413.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 borshSerialize,\n bs58Decode,\n bytesConcat,\n hexEncode,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\n\nimport type { KwilActionClient } from \"../create-kwil-client\";\n\nimport { getNearConnectionConfig } from \"./get-config\";\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 nep413BorschSchema = {\n struct: {\n tag: \"u32\",\n message: \"string\",\n nonce: { array: { type: \"u8\", len: 32 } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n };\n\n const nep413BorshParams = {\n tag: 2147484061,\n message: messageString,\n nonce: Array.from(nonce),\n recipient,\n callbackUrl,\n };\n\n const nep413BorshPayload = borshSerialize(nep413BorschSchema, nep413BorshParams);\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\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 { accountId, signature, publicKey, error } = Object.fromEntries(\n new URLSearchParams(window.location.hash.slice(1)).entries(),\n );\n\n if (signature) {\n await store.set(\"signer-address\", accountId);\n await store.set(\"signer-public-key\", publicKey);\n }\n\n const signMessageOriginal = wallet.signMessage.bind(wallet);\n\n wallet.signMessage = async ({\n message,\n recipient,\n }: SignMessageParams): Promise<SignedMessage & { nonce?: Uint8Array }> => {\n if (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 (signature && 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,\n 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, 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 { KeyPair } from \"near-api-js\";\n\nimport {\n binaryWriteUint16BE,\n borshSerialize,\n bytesConcat,\n sha256Hash,\n utf8Decode,\n} from \"@idos-network/utils/codecs\";\n\nexport function kwilNep413Signer(\n recipient: string,\n): (keyPair: KeyPair) => (messageBytes: Uint8Array) => Promise<Uint8Array> {\n return (keyPair: KeyPair) =>\n async (messageBytes: Uint8Array): Promise<Uint8Array> => {\n const message = utf8Decode(messageBytes);\n const nonceLength = 32;\n const nonce = crypto.getRandomValues(new Uint8Array(nonceLength));\n\n const nep413BorschSchema = {\n struct: {\n message: \"string\",\n nonce: { array: { type: \"u8\", len: nonceLength } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n } as const;\n\n const tag = 2147484061; // 2**31 + 413\n\n const { signature } = keyPair.sign(\n sha256Hash(\n bytesConcat(\n borshSerialize(\"u32\", tag),\n borshSerialize(nep413BorschSchema, { message, nonce, recipient }),\n ),\n ),\n );\n\n const kwilNep413BorschSchema = {\n struct: {\n tag: \"u32\",\n ...nep413BorschSchema.struct,\n },\n };\n\n const kwilNep413BorshParams = {\n tag,\n message,\n nonce,\n recipient,\n };\n\n const kwilNep413BorshPayload = borshSerialize(kwilNep413BorschSchema, kwilNep413BorshParams);\n\n return bytesConcat(\n binaryWriteUint16BE(kwilNep413BorshPayload.length),\n kwilNep413BorshPayload,\n signature,\n );\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,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ln as WalletType } from "../index-Bqz6trCk.mjs";
|
|
2
2
|
//#region src/signature-verification/index.d.ts
|
|
3
|
-
interface WalletSignature {
|
|
3
|
+
export interface WalletSignature {
|
|
4
4
|
address: string;
|
|
5
5
|
signature: string;
|
|
6
6
|
message: string;
|
|
7
7
|
wallet_type: WalletType;
|
|
8
8
|
public_key?: string[];
|
|
9
9
|
}
|
|
10
|
-
declare const verifySignature: (walletPayload: WalletSignature) => Promise<boolean>;
|
|
10
|
+
export declare const verifySignature: (walletPayload: WalletSignature) => Promise<boolean>;
|
|
11
11
|
//#endregion
|
|
12
|
-
export { WalletSignature, verifySignature };
|
|
13
12
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/signature-verification/index.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/signature-verification/index.ts"],"mappings":";;iBAUiB;EACf;EACA;EACA;EACA,aAAa;EACb;;qBAGW,kBAAyB,eAAe,oBAAkB"}
|
|
@@ -1,135 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { borshDeserialize, borshSerialize, bs58Decode, hexDecode, hexEncode, sha256Hash, utf8Encode } from "@idos-network/utils/codecs";
|
|
3
|
-
import nacl from "tweetnacl";
|
|
4
|
-
//#region src/near/signature-verification.ts
|
|
5
|
-
const verifyNearSignature = async (message, signature, publicKey) => {
|
|
6
|
-
try {
|
|
7
|
-
const pieces = publicKey.split(":");
|
|
8
|
-
if (pieces.length !== 2 || pieces[0] !== "ed25519") {
|
|
9
|
-
console.warn("Invalid NEAR public key format:", publicKey);
|
|
10
|
-
return false;
|
|
11
|
-
}
|
|
12
|
-
const publicKeyBytes = bs58Decode(pieces[1]);
|
|
13
|
-
if (publicKeyBytes.length !== 32) {
|
|
14
|
-
console.warn("Invalid NEAR public key length:", publicKeyBytes.length);
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
const signatureBytes = hexDecode(signature);
|
|
18
|
-
const payloadLength = new DataView(signatureBytes.buffer).getUint16(0, false);
|
|
19
|
-
const payloadBytes = signatureBytes.slice(2, 2 + payloadLength);
|
|
20
|
-
const actualSignature = signatureBytes.slice(2 + payloadLength);
|
|
21
|
-
if (actualSignature.length !== 64) {
|
|
22
|
-
console.warn("Invalid signature length:", actualSignature.length);
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
const payloadSchema = { struct: {
|
|
26
|
-
tag: "u32",
|
|
27
|
-
message: "string",
|
|
28
|
-
nonce: { array: {
|
|
29
|
-
type: "u8",
|
|
30
|
-
len: 32
|
|
31
|
-
} },
|
|
32
|
-
recipient: "string",
|
|
33
|
-
callbackUrl: { option: "string" }
|
|
34
|
-
} };
|
|
35
|
-
const deserializedPayload = borshDeserialize(payloadSchema, payloadBytes);
|
|
36
|
-
const hash = sha256Hash(borshSerialize(payloadSchema, {
|
|
37
|
-
tag: 2147484061,
|
|
38
|
-
message,
|
|
39
|
-
nonce: deserializedPayload.nonce,
|
|
40
|
-
recipient: deserializedPayload.recipient,
|
|
41
|
-
callbackUrl: deserializedPayload.callbackUrl
|
|
42
|
-
}));
|
|
43
|
-
return nacl.sign.detached.verify(hash, actualSignature, publicKeyBytes);
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.warn("NEAR signature verification failed:", error);
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/xrp/signature-verification.ts
|
|
51
|
-
const verifyRippleSignature = async (message, signature, publicKey) => {
|
|
52
|
-
let xrpKeypair;
|
|
53
|
-
try {
|
|
54
|
-
xrpKeypair = await import("ripple-keypairs");
|
|
55
|
-
} catch (e) {
|
|
56
|
-
throw new Error("Can't load `ripple-keypairs`", { cause: e });
|
|
57
|
-
}
|
|
58
|
-
const messageHex = hexEncode(utf8Encode(message));
|
|
59
|
-
return xrpKeypair.verify(messageHex, signature, publicKey);
|
|
60
|
-
};
|
|
61
|
-
//#endregion
|
|
62
|
-
//#region src/signature-verification/evm.ts
|
|
63
|
-
const verifyEvmSignature = async (message, signature, address) => {
|
|
64
|
-
let verifyMessage;
|
|
65
|
-
try {
|
|
66
|
-
verifyMessage = (await import("viem")).verifyMessage;
|
|
67
|
-
} catch (_e) {
|
|
68
|
-
throw new Error("Can't load viem");
|
|
69
|
-
}
|
|
70
|
-
try {
|
|
71
|
-
return await verifyMessage({
|
|
72
|
-
address,
|
|
73
|
-
message,
|
|
74
|
-
signature
|
|
75
|
-
});
|
|
76
|
-
} catch (e) {
|
|
77
|
-
console.warn("EVM signature verification failed:", e);
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
//#endregion
|
|
82
|
-
//#region src/signature-verification/facesign.ts
|
|
83
|
-
const verifyFaceSignSignature = (message, signature, publicKey) => {
|
|
84
|
-
try {
|
|
85
|
-
return nacl.sign.detached.verify(utf8Encode(message), hexDecode(signature), hexDecode(publicKey));
|
|
86
|
-
} catch (error) {
|
|
87
|
-
console.warn("FaceSign signature verification failed:", error);
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
//#endregion
|
|
92
|
-
//#region src/signature-verification/stellar.ts
|
|
93
|
-
const verifyStellarSignature = async (message, signature, publicKey) => {
|
|
94
|
-
let stellar;
|
|
95
|
-
try {
|
|
96
|
-
stellar = await import("@stellar/stellar-sdk");
|
|
97
|
-
} catch (e) {
|
|
98
|
-
throw new Error("Can't load `@stellar/stellar-sdk`", { cause: e });
|
|
99
|
-
}
|
|
100
|
-
try {
|
|
101
|
-
const signatureBuffer = Buffer.from(signature, "hex");
|
|
102
|
-
const publicKeyBuffer = Buffer.from(publicKey, "hex");
|
|
103
|
-
const strKeyAddress = stellar.StrKey.encodeEd25519PublicKey(publicKeyBuffer);
|
|
104
|
-
return stellar.Keypair.fromPublicKey(strKeyAddress).verify(Buffer.from(message), signatureBuffer);
|
|
105
|
-
} catch (error) {
|
|
106
|
-
console.warn("Stellar signature verification failed:", error);
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
//#endregion
|
|
111
|
-
//#region src/signature-verification/index.ts
|
|
112
|
-
const verifySignature = async (walletPayload) => {
|
|
113
|
-
invariant(walletPayload.address, "Wallet address is required");
|
|
114
|
-
invariant(walletPayload.message, "Wallet message is required");
|
|
115
|
-
invariant(walletPayload.signature, "Wallet signature is required");
|
|
116
|
-
invariant(walletPayload.wallet_type, "Wallet type is required");
|
|
117
|
-
if (walletPayload.wallet_type !== "EVM") invariant(walletPayload.public_key?.[0], "Wallet public_key is required for non-EVM wallets");
|
|
118
|
-
try {
|
|
119
|
-
switch (walletPayload.wallet_type) {
|
|
120
|
-
case "EVM": return verifyEvmSignature(walletPayload.message, walletPayload.signature, walletPayload.address);
|
|
121
|
-
case "NEAR": return verifyNearSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
122
|
-
case "XRPL": return verifyRippleSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
123
|
-
case "Stellar": return await verifyStellarSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
124
|
-
case "FaceSign": return verifyFaceSignSignature(walletPayload.message, walletPayload.signature, walletPayload.public_key[0]);
|
|
125
|
-
default: throw new Error(`Unsupported wallet type: ${walletPayload.wallet_type}`);
|
|
126
|
-
}
|
|
127
|
-
} catch (error) {
|
|
128
|
-
console.warn("Error verifying signature", error);
|
|
129
|
-
return false;
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
//#endregion
|
|
133
|
-
export { verifySignature };
|
|
134
|
-
|
|
1
|
+
import e from"tiny-invariant";import{borshDeserialize as t,borshSerialize as n,bs58Decode as r,hexDecode as i,hexEncode as a,sha256Hash as o,utf8Encode as s}from"@idos-network/utils/codecs";import c from"tweetnacl";const l=async(e,a,s)=>{try{let l=s.split(`:`);if(l.length!==2||l[0]!==`ed25519`)return console.warn(`Invalid NEAR public key format:`,s),!1;let u=r(l[1]);if(u.length!==32)return console.warn(`Invalid NEAR public key length:`,u.length),!1;let d=i(a),f=new DataView(d.buffer).getUint16(0,!1),p=d.slice(2,2+f),m=d.slice(2+f);if(m.length!==64)return console.warn(`Invalid signature length:`,m.length),!1;let h={struct:{tag:`u32`,message:`string`,nonce:{array:{type:`u8`,len:32}},recipient:`string`,callbackUrl:{option:`string`}}},g=t(h,p),_={tag:2147484061,message:e,nonce:g.nonce,recipient:g.recipient,callbackUrl:g.callbackUrl},v=n(h,_),y=o(v);return c.sign.detached.verify(y,m,u)}catch(e){return console.warn(`NEAR signature verification failed:`,e),!1}},u=async(e,t,n)=>{let r;try{r=await import(`ripple-keypairs`)}catch(e){throw Error("Can't load `ripple-keypairs`",{cause:e})}let i=a(s(e));return r.verify(i,t,n)},d=async(e,t,n)=>{let r;try{r=(await import(`viem`)).verifyMessage}catch{throw Error(`Can't load viem`)}try{return await r({address:n,message:e,signature:t})}catch(e){return console.warn(`EVM signature verification failed:`,e),!1}},f=(e,t,n)=>{try{return c.sign.detached.verify(s(e),i(t),i(n))}catch(e){return console.warn(`FaceSign signature verification failed:`,e),!1}},p=async(e,t,n)=>{let r;try{r=await import(`@stellar/stellar-sdk`)}catch(e){throw Error("Can't load `@stellar/stellar-sdk`",{cause:e})}try{let i=Buffer.from(t,`hex`),a=Buffer.from(n,`hex`),o=r.StrKey.encodeEd25519PublicKey(a);return r.Keypair.fromPublicKey(o).verify(Buffer.from(e),i)}catch(e){return console.warn(`Stellar signature verification failed:`,e),!1}},m=async t=>{if(e(t.address,`Wallet address is required`),e(t.wallet_type,`Wallet type is required`),t.wallet_type===`MM`)return!1;e(t.message,`Wallet message is required`),e(t.signature,`Wallet signature is required`),t.wallet_type!==`EVM`&&e(t.public_key?.[0],`Wallet public_key is required for non-EVM wallets`);try{switch(t.wallet_type){case`EVM`:return d(t.message,t.signature,t.address);case`NEAR`:return l(t.message,t.signature,t.public_key[0]);case`XRPL`:return u(t.message,t.signature,t.public_key[0]);case`Stellar`:return await p(t.message,t.signature,t.public_key[0]);case`FaceSign`:return f(t.message,t.signature,t.public_key[0]);default:throw Error(`Unsupported wallet type: ${t.wallet_type}`)}}catch(e){return console.warn(`Error verifying signature`,e),!1}};export{m as verifySignature};
|
|
135
2
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/near/signature-verification.ts","../../src/xrp/signature-verification.ts","../../src/signature-verification/evm.ts","../../src/signature-verification/facesign.ts","../../src/signature-verification/stellar.ts","../../src/signature-verification/index.ts"],"sourcesContent":["import {\n borshDeserialize,\n borshSerialize,\n bs58Decode,\n hexDecode,\n sha256Hash,\n} from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\ninterface NEP413Payload {\n tag: number;\n message: string;\n nonce: number[];\n recipient: string;\n callbackUrl?: string;\n}\n\nexport const verifyNearSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n try {\n // Parse the NEAR public key format: \"ed25519:base58_encoded_key\"\n const pieces = publicKey.split(\":\");\n if (pieces.length !== 2 || pieces[0] !== \"ed25519\") {\n console.warn(\"Invalid NEAR public key format:\", publicKey);\n return false;\n }\n\n // Extract raw public key bytes (am trying to match the logic I did in Backend)\n const publicKeyBytes = bs58Decode(pieces[1]);\n if (publicKeyBytes.length !== 32) {\n console.warn(\"Invalid NEAR public key length:\", publicKeyBytes.length);\n return false;\n }\n\n // Decode the signature from hex\n const signatureBytes = hexDecode(signature);\n\n // Deserialize the signature (matching Go's deserializeSignature)\n const payloadLength = new DataView(signatureBytes.buffer).getUint16(0, false);\n const payloadBytes = signatureBytes.slice(2, 2 + payloadLength);\n const actualSignature = signatureBytes.slice(2 + payloadLength);\n\n if (actualSignature.length !== 64) {\n console.warn(\"Invalid signature length:\", actualSignature.length);\n return false;\n }\n\n // Deserialize the payload to extract nonce, recipient, callbackUrl\n const payloadSchema = {\n struct: {\n tag: \"u32\",\n message: \"string\",\n nonce: { array: { type: \"u8\", len: 32 } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n };\n\n const deserializedPayload = borshDeserialize(payloadSchema, payloadBytes) as NEP413Payload;\n\n // Reconstruct the payload with tag and message (matching Go implementation)\n const reconstructedPayload: NEP413Payload = {\n tag: 2147484061, // 2**31 + 413\n message: message, // Use the provided message\n nonce: deserializedPayload.nonce,\n recipient: deserializedPayload.recipient,\n callbackUrl: deserializedPayload.callbackUrl,\n };\n\n // Serialize the entire payload (matching Go's borsch.Serialize(*payload))\n const fullPayloadBytes = borshSerialize(payloadSchema, reconstructedPayload);\n // Hash the payload (matching Go's sha256.Sum256(payloadBytes))\n const hash = sha256Hash(fullPayloadBytes);\n // Raw ed25519 verification using nacl (matching Go's ed25519.Verify)\n const isValid = nacl.sign.detached.verify(hash, actualSignature, publicKeyBytes);\n\n return isValid;\n } catch (error) {\n console.warn(\"NEAR signature verification failed:\", error);\n return false;\n }\n};\n","import { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\nexport const verifyRippleSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\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 const messageHex = hexEncode(utf8Encode(message));\n return xrpKeypair.verify(messageHex, signature, publicKey);\n};\n","export const verifyEvmSignature = async (\n message: string,\n signature: `0x${string}`,\n address: `0x${string}`,\n): Promise<boolean> => {\n let verifyMessage: typeof import(\"viem\").verifyMessage;\n\n try {\n verifyMessage = (await import(\"viem\")).verifyMessage;\n } catch (_e) {\n throw new Error(\"Can't load viem\");\n }\n\n try {\n return await verifyMessage({\n address,\n message,\n signature,\n });\n } catch (e) {\n console.warn(\"EVM signature verification failed:\", e);\n return false;\n }\n};\n","import { hexDecode, utf8Encode } from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nexport const verifyFaceSignSignature = (\n message: string,\n signature: string,\n publicKey: string,\n): boolean => {\n try {\n return nacl.sign.detached.verify(\n utf8Encode(message),\n hexDecode(signature),\n hexDecode(publicKey),\n );\n } catch (error) {\n console.warn(\"FaceSign signature verification failed:\", error);\n return false;\n }\n};\n","export const verifyStellarSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n let stellar: typeof import(\"@stellar/stellar-sdk\");\n\n try {\n stellar = await import(\"@stellar/stellar-sdk\");\n } catch (e) {\n throw new Error(\"Can't load `@stellar/stellar-sdk`\", { cause: e });\n }\n\n try {\n // Convert hex signature to buffer\n const signatureBuffer = Buffer.from(signature, \"hex\");\n\n // `Keypair.fromPublicKey()` expects StrKey format, but we're passing as hex (derivePublicKey result).\n const publicKeyBuffer = Buffer.from(publicKey, \"hex\");\n const strKeyAddress = stellar.StrKey.encodeEd25519PublicKey(publicKeyBuffer);\n\n const keypair = stellar.Keypair.fromPublicKey(strKeyAddress);\n\n const result = keypair.verify(Buffer.from(message), signatureBuffer);\n\n return result;\n } catch (error) {\n console.warn(\"Stellar signature verification failed:\", error);\n return false;\n }\n};\n","import invariant from \"tiny-invariant\";\n\nimport type { WalletType } from \"../actions\";\n\nimport { verifyNearSignature } from \"../near/signature-verification\";\nimport { verifyRippleSignature } from \"../xrp/signature-verification\";\nimport { verifyEvmSignature } from \"./evm\";\nimport { verifyFaceSignSignature } from \"./facesign\";\nimport { verifyStellarSignature } from \"./stellar\";\n\nexport interface WalletSignature {\n address: string;\n signature: string;\n message: string;\n wallet_type: WalletType;\n public_key?: string[];\n}\n\nexport const verifySignature = async (walletPayload: WalletSignature): Promise<boolean> => {\n invariant(walletPayload.address, \"Wallet address is required\");\n invariant(walletPayload.message, \"Wallet message is required\");\n invariant(walletPayload.signature, \"Wallet signature is required\");\n invariant(walletPayload.wallet_type, \"Wallet type is required\");\n\n if (walletPayload.wallet_type !== \"EVM\") {\n invariant(walletPayload.public_key?.[0], \"Wallet public_key is required for non-EVM wallets\");\n }\n\n try {\n switch (walletPayload.wallet_type) {\n case \"EVM\":\n return verifyEvmSignature(\n walletPayload.message,\n walletPayload.signature as `0x${string}`,\n walletPayload.address as `0x${string}`,\n );\n case \"NEAR\":\n return verifyNearSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"XRPL\":\n return verifyRippleSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"Stellar\":\n return await verifyStellarSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"FaceSign\":\n return verifyFaceSignSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n default:\n throw new Error(`Unsupported wallet type: ${walletPayload.wallet_type}`);\n }\n } catch (error) {\n console.warn(\"Error verifying signature\", error);\n return false;\n }\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/near/signature-verification.ts","../../src/xrp/signature-verification.ts","../../src/signature-verification/evm.ts","../../src/signature-verification/facesign.ts","../../src/signature-verification/stellar.ts","../../src/signature-verification/index.ts"],"sourcesContent":["import {\n borshDeserialize,\n borshSerialize,\n bs58Decode,\n hexDecode,\n sha256Hash,\n} from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\ninterface NEP413Payload {\n tag: number;\n message: string;\n nonce: number[];\n recipient: string;\n callbackUrl?: string;\n}\n\nexport const verifyNearSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n try {\n // Parse the NEAR public key format: \"ed25519:base58_encoded_key\"\n const pieces = publicKey.split(\":\");\n if (pieces.length !== 2 || pieces[0] !== \"ed25519\") {\n console.warn(\"Invalid NEAR public key format:\", publicKey);\n return false;\n }\n\n // Extract raw public key bytes (am trying to match the logic I did in Backend)\n const publicKeyBytes = bs58Decode(pieces[1]);\n if (publicKeyBytes.length !== 32) {\n console.warn(\"Invalid NEAR public key length:\", publicKeyBytes.length);\n return false;\n }\n\n // Decode the signature from hex\n const signatureBytes = hexDecode(signature);\n\n // Deserialize the signature (matching Go's deserializeSignature)\n const payloadLength = new DataView(signatureBytes.buffer).getUint16(0, false);\n const payloadBytes = signatureBytes.slice(2, 2 + payloadLength);\n const actualSignature = signatureBytes.slice(2 + payloadLength);\n\n if (actualSignature.length !== 64) {\n console.warn(\"Invalid signature length:\", actualSignature.length);\n return false;\n }\n\n // Deserialize the payload to extract nonce, recipient, callbackUrl\n const payloadSchema = {\n struct: {\n tag: \"u32\",\n message: \"string\",\n nonce: { array: { type: \"u8\", len: 32 } },\n recipient: \"string\",\n callbackUrl: { option: \"string\" },\n },\n };\n\n const deserializedPayload = borshDeserialize(payloadSchema, payloadBytes) as NEP413Payload;\n\n // Reconstruct the payload with tag and message (matching Go implementation)\n const reconstructedPayload: NEP413Payload = {\n tag: 2147484061, // 2**31 + 413\n message: message, // Use the provided message\n nonce: deserializedPayload.nonce,\n recipient: deserializedPayload.recipient,\n callbackUrl: deserializedPayload.callbackUrl,\n };\n\n // Serialize the entire payload (matching Go's borsch.Serialize(*payload))\n const fullPayloadBytes = borshSerialize(payloadSchema, reconstructedPayload);\n // Hash the payload (matching Go's sha256.Sum256(payloadBytes))\n const hash = sha256Hash(fullPayloadBytes);\n // Raw ed25519 verification using nacl (matching Go's ed25519.Verify)\n const isValid = nacl.sign.detached.verify(hash, actualSignature, publicKeyBytes);\n\n return isValid;\n } catch (error) {\n console.warn(\"NEAR signature verification failed:\", error);\n return false;\n }\n};\n","import { hexEncode, utf8Encode } from \"@idos-network/utils/codecs\";\n\nexport const verifyRippleSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\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 const messageHex = hexEncode(utf8Encode(message));\n return xrpKeypair.verify(messageHex, signature, publicKey);\n};\n","export const verifyEvmSignature = async (\n message: string,\n signature: `0x${string}`,\n address: `0x${string}`,\n): Promise<boolean> => {\n let verifyMessage: typeof import(\"viem\").verifyMessage;\n\n try {\n verifyMessage = (await import(\"viem\")).verifyMessage;\n } catch (_e) {\n throw new Error(\"Can't load viem\");\n }\n\n try {\n return await verifyMessage({\n address,\n message,\n signature,\n });\n } catch (e) {\n console.warn(\"EVM signature verification failed:\", e);\n return false;\n }\n};\n","import { hexDecode, utf8Encode } from \"@idos-network/utils/codecs\";\nimport nacl from \"tweetnacl\";\n\nexport const verifyFaceSignSignature = (\n message: string,\n signature: string,\n publicKey: string,\n): boolean => {\n try {\n return nacl.sign.detached.verify(\n utf8Encode(message),\n hexDecode(signature),\n hexDecode(publicKey),\n );\n } catch (error) {\n console.warn(\"FaceSign signature verification failed:\", error);\n return false;\n }\n};\n","export const verifyStellarSignature = async (\n message: string,\n signature: string,\n publicKey: string,\n): Promise<boolean> => {\n let stellar: typeof import(\"@stellar/stellar-sdk\");\n\n try {\n stellar = await import(\"@stellar/stellar-sdk\");\n } catch (e) {\n throw new Error(\"Can't load `@stellar/stellar-sdk`\", { cause: e });\n }\n\n try {\n // Convert hex signature to buffer\n const signatureBuffer = Buffer.from(signature, \"hex\");\n\n // `Keypair.fromPublicKey()` expects StrKey format, but we're passing as hex (derivePublicKey result).\n const publicKeyBuffer = Buffer.from(publicKey, \"hex\");\n const strKeyAddress = stellar.StrKey.encodeEd25519PublicKey(publicKeyBuffer);\n\n const keypair = stellar.Keypair.fromPublicKey(strKeyAddress);\n\n const result = keypair.verify(Buffer.from(message), signatureBuffer);\n\n return result;\n } catch (error) {\n console.warn(\"Stellar signature verification failed:\", error);\n return false;\n }\n};\n","import invariant from \"tiny-invariant\";\n\nimport type { WalletType } from \"../actions\";\n\nimport { verifyNearSignature } from \"../near/signature-verification\";\nimport { verifyRippleSignature } from \"../xrp/signature-verification\";\nimport { verifyEvmSignature } from \"./evm\";\nimport { verifyFaceSignSignature } from \"./facesign\";\nimport { verifyStellarSignature } from \"./stellar\";\n\nexport interface WalletSignature {\n address: string;\n signature: string;\n message: string;\n wallet_type: WalletType;\n public_key?: string[];\n}\n\nexport const verifySignature = async (walletPayload: WalletSignature): Promise<boolean> => {\n invariant(walletPayload.address, \"Wallet address is required\");\n invariant(walletPayload.wallet_type, \"Wallet type is required\");\n\n if (walletPayload.wallet_type === \"MM\") {\n // MM authentication requires capability validation by a trusted service such as KGW.\n return false;\n }\n\n invariant(walletPayload.message, \"Wallet message is required\");\n invariant(walletPayload.signature, \"Wallet signature is required\");\n\n if (walletPayload.wallet_type !== \"EVM\") {\n invariant(walletPayload.public_key?.[0], \"Wallet public_key is required for non-EVM wallets\");\n }\n\n try {\n switch (walletPayload.wallet_type) {\n case \"EVM\":\n return verifyEvmSignature(\n walletPayload.message,\n walletPayload.signature as `0x${string}`,\n walletPayload.address as `0x${string}`,\n );\n case \"NEAR\":\n return verifyNearSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"XRPL\":\n return verifyRippleSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"Stellar\":\n return await verifyStellarSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n case \"FaceSign\":\n return verifyFaceSignSignature(\n walletPayload.message,\n walletPayload.signature,\n // @ts-expect-error - this has been checked above\n walletPayload.public_key[0],\n );\n default:\n throw new Error(`Unsupported wallet type: ${walletPayload.wallet_type}`);\n }\n } catch (error) {\n console.warn(\"Error verifying signature\", error);\n return false;\n }\n};\n"],"mappings":"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"}
|