@heraldprotocol/mpp 0.0.3 → 0.0.5

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.
@@ -192,7 +192,7 @@ function charge2(parameters = {}) {
192
192
  });
193
193
  }
194
194
  if (mode === "push") {
195
- const receipt = await (0, import_actions.sendTransactionSync)(client, {
195
+ const hash = await (0, import_actions.sendTransaction)(client, {
196
196
  account,
197
197
  chain: client.chain,
198
198
  to: currency2,
@@ -202,7 +202,6 @@ function charge2(parameters = {}) {
202
202
  args: [recipient, amount]
203
203
  })
204
204
  });
205
- const hash = receipt.transactionHash;
206
205
  return import_mppx2.Credential.serialize({
207
206
  challenge,
208
207
  payload: { hash, type: "hash" },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/index.ts","../../src/client/Charge.ts","../../src/defaults.ts","../../src/Methods.ts","../../src/client/Methods.ts"],"sourcesContent":["export { charge } from \"./Charge.js\";\nexport { zerog } from \"./Methods.js\";\n","import type { Account, Address, Chain, Client } from \"viem\";\nimport { Credential, Method, z } from \"mppx\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { sendTransactionSync, signTypedData } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the client.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const charge = zerog.charge({\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}) {\n const resolveAccount = (\n client: Client,\n override?: Account | Address | undefined\n ): Account => {\n const raw = override ?? parameters.account;\n if (raw) return typeof raw === \"string\" ? parseAccount(raw) : raw;\n if (client.account) return client.account;\n throw new Error(\n \"No `account` provided. Pass `account` to parameters or context.\"\n );\n };\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toClient(Methods.charge, {\n context: z.object({\n account: z.optional(z.custom<Account | Address>()),\n mode: z.optional(z.enum([\"push\", \"pull\"])),\n }),\n\n async createCredential({ challenge, context }) {\n const chainId = challenge.request.methodDetails?.chainId as\n | number\n | undefined;\n const client = await resolveClient(chainId);\n const account = resolveAccount(client, context?.account);\n\n const mode =\n context?.mode ??\n parameters.mode ??\n (account.type === \"json-rpc\" ? \"push\" : \"pull\");\n\n const { request } = challenge;\n const amount = BigInt(request.amount);\n const currency = request.currency as Address;\n const recipient = request.recipient as Address;\n\n if (mode === \"pull\") {\n const tokenMeta = defaults.erc3009Tokens[currency.toLowerCase()];\n if (!tokenMeta) {\n throw new Error(\n `Token ${currency} does not support ERC-3009 (TransferWithAuthorization). ` +\n `Cannot use pull mode.`\n );\n }\n\n const resolvedChainId = chainId ?? client.chain?.id;\n if (!resolvedChainId)\n throw new Error(\"Could not determine chainId for EIP-712 domain.\");\n\n const { name: tokenName, version: tokenVersion } = tokenMeta;\n\n const validAfter = 0n;\n const validBefore = challenge.expires\n ? BigInt(Math.floor(new Date(challenge.expires).getTime() / 1000))\n : BigInt(Math.floor(Date.now() / 1000) + 3600); // 1 hour default\n const nonce = randomNonce();\n\n const signature = await signTypedData(client, {\n account,\n domain: {\n name: tokenName,\n version: tokenVersion,\n chainId: resolvedChainId,\n verifyingContract: currency,\n },\n types: {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n },\n primaryType: \"TransferWithAuthorization\",\n message: {\n from: account.address,\n to: recipient,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n },\n });\n\n return Credential.serialize({\n challenge,\n payload: {\n type: \"authorization\" as const,\n from: account.address,\n to: recipient,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n signature,\n },\n source: `did:pkh:eip155:${resolvedChainId}:${account.address}`,\n });\n }\n\n if (mode === \"push\") {\n const receipt = await sendTransactionSync(client, {\n account,\n chain: client.chain,\n to: currency,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [recipient, amount],\n }),\n });\n const hash = receipt.transactionHash;\n return Credential.serialize({\n challenge,\n payload: { hash, type: \"hash\" },\n source: `did:pkh:eip155:${chainId ?? client.chain?.id}:${account.address}`,\n });\n }\n\n throw new Error(`Unsupported mode: ${mode}`);\n },\n });\n}\n\nexport declare namespace charge {\n type Parameters = {\n /** Account to use for signing. */\n account?: Account | Address | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Controls how the charge transaction is submitted.\n *\n * - `'push'`: Client broadcasts the transaction and sends the tx hash.\n * - `'pull'`: Client signs an ERC-3009 TransferWithAuthorization\n * message. Server calls `transferWithAuthorization` and pays gas.\n *\n * @default `'push'` for JSON-RPC accounts, `'pull'` for local accounts.\n */\n mode?: \"push\" | \"pull\" | undefined;\n };\n}\n\n/** Generates a random 32-byte hex nonce. */\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n if (typeof crypto !== \"undefined\") {\n crypto.getRandomValues(bytes);\n } else if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n (globalThis as unknown as { crypto: Crypto }).crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return `0x${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n","export const chainId = {\n mainnet: 16661,\n testnet: 16602,\n} as const;\n\nexport type ChainId = (typeof chainId)[keyof typeof chainId];\n\nconst USDC_E = \"0x1f3aa82227281ca364bfb3d253b0f1af1da6473e\";\n\n/** Chain ID → default currency. */\nexport const currency: Partial<Record<ChainId, string>> = {\n [chainId.mainnet]: USDC_E,\n};\n\n/** Default token decimals for USDC.e. */\nexport const decimals = 6;\n\n/** Default RPC URLs per chain. */\nexport const rpcUrl: Record<number, string> = {\n [chainId.mainnet]: \"https://evmrpc.0g.ai\",\n [chainId.testnet]: \"https://evmrpc-testnet.0g.ai\",\n};\n\n/** ERC-3009 ABI (`transferWithAuthorization`, `receiveWithAuthorization`). */\nexport const erc3009Abi = [\n {\n type: \"function\",\n name: \"transferWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"receiveWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"name\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"version\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/**\n * Known tokens that support ERC-3009 (TransferWithAuthorization).\n * Keyed by lowercase address for case-insensitive lookup.\n */\nexport const erc3009Tokens: Record<string, { name: string; version: string }> =\n {\n [USDC_E.toLowerCase()]: {\n name: \"Bridged USDC\",\n version: \"2\",\n },\n };\n\n/** Resolves the default currency for a given chain. */\nexport function resolveCurrency(parameters: {\n chainId?: number | undefined;\n testnet?: boolean | undefined;\n}): string {\n const id =\n parameters.chainId ??\n (parameters.testnet ? chainId.testnet : chainId.mainnet);\n const resolved = currency[id as ChainId];\n if (!resolved)\n throw new Error(`No default currency configured for chainId ${id}.`);\n return resolved;\n}\n","import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` client method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/client\";\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ account })],\n * });\n * ```\n */\nexport function zerog(\n parameters: zerog.Parameters = {}\n): readonly [Method.AnyClient] {\n return [charge_(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` client method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","import_mppx","import_viem","chainId","charge","chainId","currency","charge","zerog"]}
1
+ {"version":3,"sources":["../../src/client/index.ts","../../src/client/Charge.ts","../../src/defaults.ts","../../src/Methods.ts","../../src/client/Methods.ts"],"sourcesContent":["export { charge } from \"./Charge.js\";\nexport { zerog } from \"./Methods.js\";\n","import type { Account, Address, Chain, Client } from \"viem\";\nimport { Credential, Method, z } from \"mppx\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { sendTransaction, signTypedData } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the client.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const charge = zerog.charge({\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}) {\n const resolveAccount = (\n client: Client,\n override?: Account | Address | undefined\n ): Account => {\n const raw = override ?? parameters.account;\n if (raw) return typeof raw === \"string\" ? parseAccount(raw) : raw;\n if (client.account) return client.account;\n throw new Error(\n \"No `account` provided. Pass `account` to parameters or context.\"\n );\n };\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toClient(Methods.charge, {\n context: z.object({\n account: z.optional(z.custom<Account | Address>()),\n mode: z.optional(z.enum([\"push\", \"pull\"])),\n }),\n\n async createCredential({ challenge, context }) {\n const chainId = challenge.request.methodDetails?.chainId as\n | number\n | undefined;\n const client = await resolveClient(chainId);\n const account = resolveAccount(client, context?.account);\n\n const mode =\n context?.mode ??\n parameters.mode ??\n (account.type === \"json-rpc\" ? \"push\" : \"pull\");\n\n const { request } = challenge;\n const amount = BigInt(request.amount);\n const currency = request.currency as Address;\n const recipient = request.recipient as Address;\n\n if (mode === \"pull\") {\n const tokenMeta = defaults.erc3009Tokens[currency.toLowerCase()];\n if (!tokenMeta) {\n throw new Error(\n `Token ${currency} does not support ERC-3009 (TransferWithAuthorization). ` +\n `Cannot use pull mode.`\n );\n }\n\n const resolvedChainId = chainId ?? client.chain?.id;\n if (!resolvedChainId)\n throw new Error(\"Could not determine chainId for EIP-712 domain.\");\n\n const { name: tokenName, version: tokenVersion } = tokenMeta;\n\n const validAfter = 0n;\n const validBefore = challenge.expires\n ? BigInt(Math.floor(new Date(challenge.expires).getTime() / 1000))\n : BigInt(Math.floor(Date.now() / 1000) + 3600); // 1 hour default\n const nonce = randomNonce();\n\n const signature = await signTypedData(client, {\n account,\n domain: {\n name: tokenName,\n version: tokenVersion,\n chainId: resolvedChainId,\n verifyingContract: currency,\n },\n types: {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n },\n primaryType: \"TransferWithAuthorization\",\n message: {\n from: account.address,\n to: recipient,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n },\n });\n\n return Credential.serialize({\n challenge,\n payload: {\n type: \"authorization\" as const,\n from: account.address,\n to: recipient,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n signature,\n },\n source: `did:pkh:eip155:${resolvedChainId}:${account.address}`,\n });\n }\n\n if (mode === \"push\") {\n const hash = await sendTransaction(client, {\n account,\n chain: client.chain,\n to: currency,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [recipient, amount] as const,\n }),\n });\n\n return Credential.serialize({\n challenge,\n payload: { hash, type: \"hash\" },\n source: `did:pkh:eip155:${chainId ?? client.chain?.id}:${account.address}`,\n });\n }\n\n throw new Error(`Unsupported mode: ${mode}`);\n },\n });\n}\n\nexport declare namespace charge {\n type Parameters = {\n /** Account to use for signing. */\n account?: Account | Address | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Controls how the charge transaction is submitted.\n *\n * - `'push'`: Client broadcasts the transaction and sends the tx hash.\n * - `'pull'`: Client signs an ERC-3009 TransferWithAuthorization\n * message. Server calls `transferWithAuthorization` and pays gas.\n *\n * @default `'push'` for JSON-RPC accounts, `'pull'` for local accounts.\n */\n mode?: \"push\" | \"pull\" | undefined;\n };\n}\n\n/** Generates a random 32-byte hex nonce. */\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n if (typeof crypto !== \"undefined\") {\n crypto.getRandomValues(bytes);\n } else if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n (globalThis as unknown as { crypto: Crypto }).crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return `0x${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n","export const chainId = {\n mainnet: 16661,\n testnet: 16602,\n} as const;\n\nexport type ChainId = (typeof chainId)[keyof typeof chainId];\n\nconst USDC_E = \"0x1f3aa82227281ca364bfb3d253b0f1af1da6473e\";\n\n/** Chain ID → default currency. */\nexport const currency: Partial<Record<ChainId, string>> = {\n [chainId.mainnet]: USDC_E,\n};\n\n/** Default token decimals for USDC.e. */\nexport const decimals = 6;\n\n/** Default RPC URLs per chain. */\nexport const rpcUrl: Record<number, string> = {\n [chainId.mainnet]: \"https://evmrpc.0g.ai\",\n [chainId.testnet]: \"https://evmrpc-testnet.0g.ai\",\n};\n\n/** ERC-3009 ABI (`transferWithAuthorization`, `receiveWithAuthorization`). */\nexport const erc3009Abi = [\n {\n type: \"function\",\n name: \"transferWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"receiveWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"name\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"version\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/**\n * Known tokens that support ERC-3009 (TransferWithAuthorization).\n * Keyed by lowercase address for case-insensitive lookup.\n */\nexport const erc3009Tokens: Record<string, { name: string; version: string }> =\n {\n [USDC_E.toLowerCase()]: {\n name: \"Bridged USDC\",\n version: \"2\",\n },\n };\n\n/** Resolves the default currency for a given chain. */\nexport function resolveCurrency(parameters: {\n chainId?: number | undefined;\n testnet?: boolean | undefined;\n}): string {\n const id =\n parameters.chainId ??\n (parameters.testnet ? chainId.testnet : chainId.mainnet);\n const resolved = currency[id as ChainId];\n if (!resolved)\n throw new Error(`No default currency configured for chainId ${id}.`);\n return resolved;\n}\n","import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` client method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/client\";\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ account })],\n * });\n * ```\n */\nexport function zerog(\n parameters: zerog.Parameters = {}\n): readonly [Method.AnyClient] {\n return [charge_(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` client method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA,gBAAAA;AAAA,EAAA;AAAA;AAAA;;;ACCA,IAAAC,eAAsC;AACtC,IAAAC,eAA6C;AAC7C,sBAA6B;AAC7B,qBAA+C;;;ACJxC,IAAM,UAAU;AAAA,EACrB,SAAS;AAAA,EACT,SAAS;AACX;AAIA,IAAM,SAAS;AAGR,IAAM,WAA6C;AAAA,EACxD,CAAC,QAAQ,OAAO,GAAG;AACrB;AAMO,IAAM,SAAiC;AAAA,EAC5C,CAAC,QAAQ,OAAO,GAAG;AAAA,EACnB,CAAC,QAAQ,OAAO,GAAG;AACrB;AA0DO,IAAM,gBACX;AAAA,EACE,CAAC,OAAO,YAAY,CAAC,GAAG;AAAA,IACtB,MAAM;AAAA,IACN,SAAS;AAAA,EACX;AACF;;;ACrFF,kBAA0B;AAC1B,kBAA2B;AAKpB,IAAM,SAAS,mBAAO,KAAK;AAAA,EAChC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,QAAQ;AAAA,IACN,YAAY;AAAA,MACV,SAAS,cAAE,mBAAmB,QAAQ;AAAA,QACpC,cAAE,OAAO,EAAE,MAAM,cAAE,KAAK,GAAG,MAAM,cAAE,QAAQ,MAAM,EAAE,CAAC;AAAA,QACpD,cAAE,OAAO;AAAA,UACP,MAAM,cAAE,QAAQ,eAAe;AAAA,UAC/B,MAAM,cAAE,OAAO;AAAA,UACf,IAAI,cAAE,OAAO;AAAA,UACb,OAAO,cAAE,OAAO;AAAA,UAChB,YAAY,cAAE,OAAO;AAAA,UACrB,aAAa,cAAE,OAAO;AAAA,UACtB,OAAO,cAAE,OAAO;AAAA,UAChB,WAAW,cAAE,OAAO;AAAA,QACtB,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AAAA,IACA,SAAS,cAAE;AAAA,MACT,cAAE,OAAO;AAAA,QACP,QAAQ,cAAE,OAAO;AAAA,QACjB,SAAS,cAAE,SAAS,cAAE,OAAO,CAAC;AAAA,QAC9B,UAAU,cAAE,OAAO;AAAA,QACnB,UAAU,cAAE,OAAO;AAAA,QACnB,aAAa,cAAE,SAAS,cAAE,OAAO,CAAC;AAAA,QAClC,YAAY,cAAE,SAAS,cAAE,OAAO,CAAC;AAAA,QACjC,WAAW,cAAE,SAAS,cAAE,OAAO,CAAC;AAAA,MAClC,CAAC;AAAA,MACD,cAAE,UAAU,CAAC,EAAE,QAAQ,SAAAC,UAAS,UAAU,GAAG,KAAK,OAAO;AAAA,QACvD,GAAG;AAAA,QACH,YAAQ,wBAAW,QAAQ,QAAQ,EAAE,SAAS;AAAA,QAC9C,GAAIA,aAAY,SAAY,EAAE,eAAe,EAAE,SAAAA,SAAQ,EAAE,IAAI,CAAC;AAAA,MAChE,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;;;AFnBM,SAASC,QAAO,aAAgC,CAAC,GAAG;AACzD,QAAM,iBAAiB,CACrB,QACA,aACY;AACZ,UAAM,MAAM,YAAY,WAAW;AACnC,QAAI,IAAK,QAAO,OAAO,QAAQ,eAAW,8BAAa,GAAG,IAAI;AAC9D,QAAI,OAAO,QAAS,QAAO,OAAO;AAClC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,gBAAgB,OACpBC,aACoB;AACpB,QAAI,WAAW,UAAW,QAAO,WAAW,UAAU,EAAE,SAAAA,SAAQ,CAAC;AACjE,UAAM,KAAKA,YAAoB,QAAQ;AACvC,UAAM,MAAe,OAAO,EAAE;AAC9B,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,qCAAqC,EAAE,GAAG;AACpE,UAAM,EAAE,cAAc,KAAK,IAAI,MAAM,OAAO,MAAM;AAClD,WAAO,aAAa,EAAE,OAAO,EAAE,GAAG,GAAY,WAAW,KAAK,GAAG,EAAE,CAAC;AAAA,EACtE;AAEA,SAAO,oBAAO,SAAiB,QAAQ;AAAA,IACrC,SAAS,eAAE,OAAO;AAAA,MAChB,SAAS,eAAE,SAAS,eAAE,OAA0B,CAAC;AAAA,MACjD,MAAM,eAAE,SAAS,eAAE,KAAK,CAAC,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC3C,CAAC;AAAA,IAED,MAAM,iBAAiB,EAAE,WAAW,QAAQ,GAAG;AAC7C,YAAMA,WAAU,UAAU,QAAQ,eAAe;AAGjD,YAAM,SAAS,MAAM,cAAcA,QAAO;AAC1C,YAAM,UAAU,eAAe,QAAQ,SAAS,OAAO;AAEvD,YAAM,OACJ,SAAS,QACT,WAAW,SACV,QAAQ,SAAS,aAAa,SAAS;AAE1C,YAAM,EAAE,QAAQ,IAAI;AACpB,YAAM,SAAS,OAAO,QAAQ,MAAM;AACpC,YAAMC,YAAW,QAAQ;AACzB,YAAM,YAAY,QAAQ;AAE1B,UAAI,SAAS,QAAQ;AACnB,cAAM,YAAqB,cAAcA,UAAS,YAAY,CAAC;AAC/D,YAAI,CAAC,WAAW;AACd,gBAAM,IAAI;AAAA,YACR,SAASA,SAAQ;AAAA,UAEnB;AAAA,QACF;AAEA,cAAM,kBAAkBD,YAAW,OAAO,OAAO;AACjD,YAAI,CAAC;AACH,gBAAM,IAAI,MAAM,iDAAiD;AAEnE,cAAM,EAAE,MAAM,WAAW,SAAS,aAAa,IAAI;AAEnD,cAAM,aAAa;AACnB,cAAM,cAAc,UAAU,UAC1B,OAAO,KAAK,MAAM,IAAI,KAAK,UAAU,OAAO,EAAE,QAAQ,IAAI,GAAI,CAAC,IAC/D,OAAO,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAI,IAAI;AAC/C,cAAM,QAAQ,YAAY;AAE1B,cAAM,YAAY,UAAM,8BAAc,QAAQ;AAAA,UAC5C;AAAA,UACA,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,SAAS;AAAA,YACT,SAAS;AAAA,YACT,mBAAmBC;AAAA,UACrB;AAAA,UACA,OAAO;AAAA,YACL,2BAA2B;AAAA,cACzB,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,cAChC,EAAE,MAAM,MAAM,MAAM,UAAU;AAAA,cAC9B,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,cACjC,EAAE,MAAM,cAAc,MAAM,UAAU;AAAA,cACtC,EAAE,MAAM,eAAe,MAAM,UAAU;AAAA,cACvC,EAAE,MAAM,SAAS,MAAM,UAAU;AAAA,YACnC;AAAA,UACF;AAAA,UACA,aAAa;AAAA,UACb,SAAS;AAAA,YACP,MAAM,QAAQ;AAAA,YACd,IAAI;AAAA,YACJ,OAAO;AAAA,YACP;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF,CAAC;AAED,eAAO,wBAAW,UAAU;AAAA,UAC1B;AAAA,UACA,SAAS;AAAA,YACP,MAAM;AAAA,YACN,MAAM,QAAQ;AAAA,YACd,IAAI;AAAA,YACJ,OAAO,OAAO,SAAS;AAAA,YACvB,YAAY,WAAW,SAAS;AAAA,YAChC,aAAa,YAAY,SAAS;AAAA,YAClC;AAAA,YACA;AAAA,UACF;AAAA,UACA,QAAQ,kBAAkB,eAAe,IAAI,QAAQ,OAAO;AAAA,QAC9D,CAAC;AAAA,MACH;AAEA,UAAI,SAAS,QAAQ;AACnB,cAAM,OAAO,UAAM,gCAAgB,QAAQ;AAAA,UACzC;AAAA,UACA,OAAO,OAAO;AAAA,UACd,IAAIA;AAAA,UACJ,UAAM,iCAAmB;AAAA,YACvB,KAAK;AAAA,YACL,cAAc;AAAA,YACd,MAAM,CAAC,WAAW,MAAM;AAAA,UAC1B,CAAC;AAAA,QACH,CAAC;AAED,eAAO,wBAAW,UAAU;AAAA,UAC1B;AAAA,UACA,SAAS,EAAE,MAAM,MAAM,OAAO;AAAA,UAC9B,QAAQ,kBAAkBD,YAAW,OAAO,OAAO,EAAE,IAAI,QAAQ,OAAO;AAAA,QAC1E,CAAC;AAAA,MACH;AAEA,YAAM,IAAI,MAAM,qBAAqB,IAAI,EAAE;AAAA,IAC7C;AAAA,EACF,CAAC;AACH;AAwBA,SAAS,cAA6B;AACpC,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,gBAAgB,KAAK;AAAA,EAC9B,WAAW,OAAO,eAAe,eAAe,YAAY,YAAY;AACtE,IAAC,WAA6C,OAAO,gBAAgB,KAAK;AAAA,EAC5E,OAAO;AACL,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,CAAC,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,GAAG;AAAA,IAC3C;AAAA,EACF;AACA,SAAO,KAAK,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AAC7E;;;AGjLO,SAAS,MACd,aAA+B,CAAC,GACH;AAC7B,SAAO,CAACE,QAAQ,UAAU,CAAC;AAC7B;AAAA,CAEO,CAAUC,WAAV;AAIE,EAAMA,OAAA,SAASD;AAAA,GAJP;","names":["charge","import_mppx","import_viem","chainId","charge","chainId","currency","charge","zerog"]}
@@ -282,33 +282,10 @@ function charge2(parameters = {}) {
282
282
  `ERC-3009 authorization expired (validBefore: ${validBefore}).`
283
283
  );
284
284
  }
285
- const hash = (0, import_viem2.keccak256)(signature);
286
- await assertHashUnused(store, hash);
287
- await markHashUsed(store, hash);
288
- if (waitForConfirmation) {
289
- const receipt = await (0, import_actions.sendTransactionSync)(client, {
290
- account: serverAccount,
291
- chain: client.chain,
292
- to: challengeCurrency,
293
- data: (0, import_viem2.encodeFunctionData)({
294
- abi: erc3009Abi,
295
- functionName: "transferWithAuthorization",
296
- args: [
297
- from,
298
- to,
299
- BigInt(value),
300
- BigInt(validAfter),
301
- BigInt(validBefore),
302
- nonce,
303
- v,
304
- r,
305
- s
306
- ]
307
- })
308
- });
309
- return toReceipt(receipt);
310
- }
311
- const txHash = await (0, import_actions.sendTransaction)(client, {
285
+ const signatureHash = (0, import_viem2.keccak256)(signature);
286
+ await assertHashUnused(store, signatureHash);
287
+ await markHashUsed(store, signatureHash);
288
+ const hash = await (0, import_actions.sendTransaction)(client, {
312
289
  account: serverAccount,
313
290
  chain: client.chain,
314
291
  to: challengeCurrency,
@@ -328,11 +305,17 @@ function charge2(parameters = {}) {
328
305
  ]
329
306
  })
330
307
  });
308
+ if (waitForConfirmation) {
309
+ const receipt = await (0, import_actions.getTransactionReceipt)(client, {
310
+ hash
311
+ });
312
+ return toReceipt(receipt);
313
+ }
331
314
  return {
332
315
  method: "zerog",
333
316
  status: "success",
334
317
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
335
- reference: txHash
318
+ reference: hash
336
319
  };
337
320
  }
338
321
  default:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/index.ts","../../src/server/Charge.ts","../../src/defaults.ts","../../src/Methods.ts","../../src/server/Methods.ts"],"sourcesContent":["export { charge } from \"./Charge.js\";\nexport { zerog } from \"./Methods.js\";\n","import type { Account, Address, Chain, Client, TransactionReceipt } from \"viem\";\nimport { Method, Store } from \"mppx\";\nimport {\n encodeFunctionData,\n erc20Abi,\n isAddressEqual,\n keccak256,\n parseEventLogs,\n} from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport {\n getTransactionReceipt,\n sendTransaction,\n sendTransactionSync,\n} from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the server.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const charge = zerog.charge({\n * recipient: \"0x...\",\n * currency: \"0x...\",\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}): Method.AnyServer {\n const {\n amount,\n currency = defaults.resolveCurrency(parameters),\n decimals = defaults.decimals,\n description,\n externalId,\n recipient,\n waitForConfirmation = true,\n } = parameters;\n const store = (parameters.store ??\n Store.memory()) as Store.Store<charge.StoreItemMap>;\n\n if (currency.toLowerCase() in defaults.erc3009Tokens && !parameters.account) {\n throw new Error(\n \"ERC-3009 requires an `account` parameter so the server can sign and broadcast \" +\n \"the transferWithAuthorization transaction.\"\n );\n }\n\n const serverAccount = parameters.account\n ? typeof parameters.account === \"string\"\n ? parseAccount(parameters.account)\n : parameters.account\n : undefined;\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toServer(Methods.charge, {\n defaults: {\n amount,\n currency,\n decimals,\n description,\n externalId,\n recipient,\n } as never,\n\n async request({ request }) {\n const chainId = await (async () => {\n if (request.chainId) return request.chainId;\n if (parameters.testnet) return defaults.chainId.testnet;\n return (await resolveClient(undefined)).chain?.id;\n })();\n\n const client = await (async () => {\n try {\n return await resolveClient(chainId);\n } catch {\n throw new Error(`No client configured with chainId ${chainId}.`);\n }\n })();\n if (client.chain?.id !== chainId)\n throw new Error(`Client not configured with chainId ${chainId}.`);\n\n return { ...request, chainId };\n },\n\n async verify({ credential, request }) {\n const { challenge } = credential;\n const { chainId } = request;\n\n const client = await resolveClient(chainId);\n\n const { request: challengeRequest } = challenge;\n const challengeAmount = challengeRequest.amount as string;\n const challengeCurrency = challengeRequest.currency as Address;\n const challengeRecipient = challengeRequest.recipient as Address;\n const expires = challenge.expires;\n\n if (expires && new Date(expires) < new Date()) {\n throw new Error(`Payment expired at ${expires}.`);\n }\n\n const payload = credential.payload;\n\n switch (payload.type) {\n case \"hash\": {\n const hash = payload.hash as `0x${string}`;\n await assertHashUnused(store, hash);\n\n const sender = extractDidAddress(credential.source);\n if (!sender)\n throw new Error(\n \"Hash credential is missing a valid `source` DID — cannot verify sender.\"\n );\n\n const receipt = await getTransactionReceipt(client, { hash });\n\n const transferLogs = parseEventLogs({\n abi: erc20Abi,\n eventName: \"Transfer\",\n logs: receipt.logs,\n });\n\n const match = transferLogs.find(\n (log) =>\n isAddressEqual(log.address, challengeCurrency) &&\n isAddressEqual(log.args.from, sender) &&\n isAddressEqual(log.args.to, challengeRecipient) &&\n log.args.value.toString() === challengeAmount\n );\n\n if (!match)\n throw new MismatchError(\n \"Payment verification failed: no matching ERC-20 transfer found.\",\n {\n sender,\n amount: challengeAmount,\n currency: challengeCurrency,\n recipient: challengeRecipient,\n }\n );\n\n await markHashUsed(store, hash);\n\n return toReceipt(receipt);\n }\n\n case \"authorization\": {\n if (!serverAccount) {\n throw new Error(\n \"Received ERC-3009 authorization credential but no server `account` is configured. \" +\n \"Set `account` in charge parameters to broadcast transferWithAuthorization.\"\n );\n }\n\n const { from, to, value, validAfter, validBefore, nonce, signature } =\n payload as {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n signature: string;\n };\n\n // Split signature into v, r, s for the contract call\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Validate authorization parameters match the challenge\n if (!isAddressEqual(to as Address, challengeRecipient))\n throw new MismatchError(\n \"Authorization recipient does not match challenge.\",\n { expected: challengeRecipient, actual: to }\n );\n\n if (value !== challengeAmount)\n throw new MismatchError(\n \"Authorization amount does not match challenge.\",\n { expected: challengeAmount, actual: value }\n );\n\n // Check expiry from the authorization itself\n const validBeforeTs = Number(validBefore);\n if (\n validBeforeTs > 0 &&\n validBeforeTs < Math.floor(Date.now() / 1000)\n ) {\n throw new Error(\n `ERC-3009 authorization expired (validBefore: ${validBefore}).`\n );\n }\n\n const hash = keccak256(signature as `0x${string}`);\n await assertHashUnused(store, hash);\n await markHashUsed(store, hash);\n\n if (waitForConfirmation) {\n const receipt = await sendTransactionSync(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return toReceipt(receipt);\n }\n\n const txHash = await sendTransaction(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: txHash,\n };\n }\n\n default:\n throw new Error(\n `Unsupported credential type \"${(payload as { type: string }).type}\".`\n );\n }\n },\n });\n}\n\nexport declare namespace charge {\n type StoreItemMap = {\n [key: `mppx:charge:${string}`]: number;\n };\n\n type Parameters = {\n /** Default payment amount (human-readable, e.g. \"1.50\"). */\n amount?: string | undefined;\n /** ERC-20 token contract address. */\n currency?: string | undefined;\n /** Token decimals. @default 6 */\n decimals?: number | undefined;\n /** Human-readable description. */\n description?: string | undefined;\n /** External identifier to echo back in receipt. */\n externalId?: string | undefined;\n /** Recipient address for payments. */\n recipient?: string | undefined;\n /** Testnet mode. */\n testnet?: boolean | undefined;\n /**\n * Whether to wait for the charge transaction to confirm on-chain.\n * @default true\n */\n waitForConfirmation?: boolean | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Server account used to broadcast `transferWithAuthorization` transactions.\n * Required when accepting `authorization` payloads. The server pays gas\n * from this account.\n */\n account?: Account | Address | undefined;\n /**\n * Store for transaction hash replay protection.\n *\n * Use a shared store in multi-instance deployments so consumed hashes are\n * visible across all server instances.\n */\n store?: Store.Store | undefined;\n };\n}\n\n/** @internal */\nfunction getHashStoreKey(hash: `0x${string}`): `mppx:charge:${string}` {\n return `mppx:charge:${hash.toLowerCase()}`;\n}\n\n/** @internal */\nasync function assertHashUnused(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n const seen = await store.get(getHashStoreKey(hash));\n if (seen !== null) throw new Error(\"Transaction hash has already been used.\");\n}\n\n/** @internal */\nasync function markHashUsed(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n await store.put(getHashStoreKey(hash), Date.now());\n}\n\n/** @internal */\nfunction toReceipt(receipt: TransactionReceipt) {\n const { status, transactionHash } = receipt;\n if (status !== \"success\") {\n throw new Error(`Transaction reverted: ${transactionHash}`);\n }\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: transactionHash,\n };\n}\n\n/**\n * Extracts an Ethereum address from a `did:pkh:eip155:<chainId>:<address>` DID.\n * Returns `undefined` if the source is missing or malformed.\n * @internal\n */\nfunction extractDidAddress(source: string | undefined): Address | undefined {\n if (!source) return undefined;\n const match = /^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/.exec(source);\n return match ? (match[1] as Address) : undefined;\n}\n\n/** @internal */\nclass MismatchError extends Error {\n override readonly name = \"MismatchError\";\n\n constructor(reason: string, details: Record<string, string>) {\n super(\n [\n reason,\n ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`),\n ].join(\"\\n\")\n );\n }\n}\n","export const chainId = {\n mainnet: 16661,\n testnet: 16602,\n} as const;\n\nexport type ChainId = (typeof chainId)[keyof typeof chainId];\n\nconst USDC_E = \"0x1f3aa82227281ca364bfb3d253b0f1af1da6473e\";\n\n/** Chain ID → default currency. */\nexport const currency: Partial<Record<ChainId, string>> = {\n [chainId.mainnet]: USDC_E,\n};\n\n/** Default token decimals for USDC.e. */\nexport const decimals = 6;\n\n/** Default RPC URLs per chain. */\nexport const rpcUrl: Record<number, string> = {\n [chainId.mainnet]: \"https://evmrpc.0g.ai\",\n [chainId.testnet]: \"https://evmrpc-testnet.0g.ai\",\n};\n\n/** ERC-3009 ABI (`transferWithAuthorization`, `receiveWithAuthorization`). */\nexport const erc3009Abi = [\n {\n type: \"function\",\n name: \"transferWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"receiveWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"name\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"version\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/**\n * Known tokens that support ERC-3009 (TransferWithAuthorization).\n * Keyed by lowercase address for case-insensitive lookup.\n */\nexport const erc3009Tokens: Record<string, { name: string; version: string }> =\n {\n [USDC_E.toLowerCase()]: {\n name: \"Bridged USDC\",\n version: \"2\",\n },\n };\n\n/** Resolves the default currency for a given chain. */\nexport function resolveCurrency(parameters: {\n chainId?: number | undefined;\n testnet?: boolean | undefined;\n}): string {\n const id =\n parameters.chainId ??\n (parameters.testnet ? chainId.testnet : chainId.mainnet);\n const resolved = currency[id as ChainId];\n if (!resolved)\n throw new Error(`No default currency configured for chainId ${id}.`);\n return resolved;\n}\n","import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` server method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/server\";\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ recipient: \"0x...\", currency: \"0x...\" })],\n * });\n * ```\n */\nexport function zerog(\n parameters?: zerog.Parameters\n): readonly [Method.AnyServer] {\n return [zerog.charge(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","import_mppx","import_viem","chainId","decimals","charge","currency","decimals","chainId","zerog","charge"]}
1
+ {"version":3,"sources":["../../src/server/index.ts","../../src/server/Charge.ts","../../src/defaults.ts","../../src/Methods.ts","../../src/server/Methods.ts"],"sourcesContent":["export { charge } from \"./Charge.js\";\nexport { zerog } from \"./Methods.js\";\n","import type { Account, Address, Chain, Client, TransactionReceipt } from \"viem\";\nimport { Method, Store } from \"mppx\";\nimport {\n encodeFunctionData,\n erc20Abi,\n isAddressEqual,\n keccak256,\n parseEventLogs,\n} from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { getTransactionReceipt, sendTransaction } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the server.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const charge = zerog.charge({\n * recipient: \"0x...\",\n * currency: \"0x...\",\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}): Method.AnyServer {\n const {\n amount,\n currency = defaults.resolveCurrency(parameters),\n decimals = defaults.decimals,\n description,\n externalId,\n recipient,\n waitForConfirmation = true,\n } = parameters;\n const store = (parameters.store ??\n Store.memory()) as Store.Store<charge.StoreItemMap>;\n\n if (currency.toLowerCase() in defaults.erc3009Tokens && !parameters.account) {\n throw new Error(\n \"ERC-3009 requires an `account` parameter so the server can sign and broadcast \" +\n \"the transferWithAuthorization transaction.\"\n );\n }\n\n const serverAccount = parameters.account\n ? typeof parameters.account === \"string\"\n ? parseAccount(parameters.account)\n : parameters.account\n : undefined;\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toServer(Methods.charge, {\n defaults: {\n amount,\n currency,\n decimals,\n description,\n externalId,\n recipient,\n } as never,\n\n async request({ request }) {\n const chainId = await (async () => {\n if (request.chainId) return request.chainId;\n if (parameters.testnet) return defaults.chainId.testnet;\n return (await resolveClient(undefined)).chain?.id;\n })();\n\n const client = await (async () => {\n try {\n return await resolveClient(chainId);\n } catch {\n throw new Error(`No client configured with chainId ${chainId}.`);\n }\n })();\n if (client.chain?.id !== chainId)\n throw new Error(`Client not configured with chainId ${chainId}.`);\n\n return { ...request, chainId };\n },\n\n async verify({ credential, request }) {\n const { challenge } = credential;\n const { chainId } = request;\n\n const client = await resolveClient(chainId);\n\n const { request: challengeRequest } = challenge;\n const challengeAmount = challengeRequest.amount as string;\n const challengeCurrency = challengeRequest.currency as Address;\n const challengeRecipient = challengeRequest.recipient as Address;\n const expires = challenge.expires;\n\n if (expires && new Date(expires) < new Date()) {\n throw new Error(`Payment expired at ${expires}.`);\n }\n\n const payload = credential.payload;\n\n switch (payload.type) {\n case \"hash\": {\n const hash = payload.hash as `0x${string}`;\n await assertHashUnused(store, hash);\n\n const sender = extractDidAddress(credential.source);\n if (!sender)\n throw new Error(\n \"Hash credential is missing a valid `source` DID — cannot verify sender.\"\n );\n\n const receipt = await getTransactionReceipt(client, { hash });\n\n const transferLogs = parseEventLogs({\n abi: erc20Abi,\n eventName: \"Transfer\",\n logs: receipt.logs,\n });\n\n const match = transferLogs.find(\n (log) =>\n isAddressEqual(log.address, challengeCurrency) &&\n isAddressEqual(log.args.from, sender) &&\n isAddressEqual(log.args.to, challengeRecipient) &&\n log.args.value.toString() === challengeAmount\n );\n\n if (!match)\n throw new MismatchError(\n \"Payment verification failed: no matching ERC-20 transfer found.\",\n {\n sender,\n amount: challengeAmount,\n currency: challengeCurrency,\n recipient: challengeRecipient,\n }\n );\n\n await markHashUsed(store, hash);\n\n return toReceipt(receipt);\n }\n\n case \"authorization\": {\n if (!serverAccount) {\n throw new Error(\n \"Received ERC-3009 authorization credential but no server `account` is configured. \" +\n \"Set `account` in charge parameters to broadcast transferWithAuthorization.\"\n );\n }\n\n const { from, to, value, validAfter, validBefore, nonce, signature } =\n payload as {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n signature: string;\n };\n\n // Split signature into v, r, s for the contract call\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Validate authorization parameters match the challenge\n if (!isAddressEqual(to as Address, challengeRecipient))\n throw new MismatchError(\n \"Authorization recipient does not match challenge.\",\n { expected: challengeRecipient, actual: to }\n );\n\n if (value !== challengeAmount)\n throw new MismatchError(\n \"Authorization amount does not match challenge.\",\n { expected: challengeAmount, actual: value }\n );\n\n // Check expiry from the authorization itself\n const validBeforeTs = Number(validBefore);\n if (\n validBeforeTs > 0 &&\n validBeforeTs < Math.floor(Date.now() / 1000)\n ) {\n throw new Error(\n `ERC-3009 authorization expired (validBefore: ${validBefore}).`\n );\n }\n\n const signatureHash = keccak256(signature as `0x${string}`);\n await assertHashUnused(store, signatureHash);\n await markHashUsed(store, signatureHash);\n\n const hash = await sendTransaction(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n if (waitForConfirmation) {\n const receipt = await getTransactionReceipt(client, {\n hash,\n });\n\n return toReceipt(receipt);\n }\n\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: hash,\n };\n }\n\n default:\n throw new Error(\n `Unsupported credential type \"${(payload as { type: string }).type}\".`\n );\n }\n },\n });\n}\n\nexport declare namespace charge {\n type StoreItemMap = {\n [key: `mppx:charge:${string}`]: number;\n };\n\n type Parameters = {\n /** Default payment amount (human-readable, e.g. \"1.50\"). */\n amount?: string | undefined;\n /** ERC-20 token contract address. */\n currency?: string | undefined;\n /** Token decimals. @default 6 */\n decimals?: number | undefined;\n /** Human-readable description. */\n description?: string | undefined;\n /** External identifier to echo back in receipt. */\n externalId?: string | undefined;\n /** Recipient address for payments. */\n recipient?: string | undefined;\n /** Testnet mode. */\n testnet?: boolean | undefined;\n /**\n * Whether to wait for the charge transaction to confirm on-chain.\n * @default true\n */\n waitForConfirmation?: boolean | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Server account used to broadcast `transferWithAuthorization` transactions.\n * Required when accepting `authorization` payloads. The server pays gas\n * from this account.\n */\n account?: Account | Address | undefined;\n /**\n * Store for transaction hash replay protection.\n *\n * Use a shared store in multi-instance deployments so consumed hashes are\n * visible across all server instances.\n */\n store?: Store.Store | undefined;\n };\n}\n\n/** @internal */\nfunction getHashStoreKey(hash: `0x${string}`): `mppx:charge:${string}` {\n return `mppx:charge:${hash.toLowerCase()}`;\n}\n\n/** @internal */\nasync function assertHashUnused(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n const seen = await store.get(getHashStoreKey(hash));\n if (seen !== null) throw new Error(\"Transaction hash has already been used.\");\n}\n\n/** @internal */\nasync function markHashUsed(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n await store.put(getHashStoreKey(hash), Date.now());\n}\n\n/** @internal */\nfunction toReceipt(receipt: TransactionReceipt) {\n const { status, transactionHash } = receipt;\n if (status !== \"success\") {\n throw new Error(`Transaction reverted: ${transactionHash}`);\n }\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: transactionHash,\n };\n}\n\n/**\n * Extracts an Ethereum address from a `did:pkh:eip155:<chainId>:<address>` DID.\n * Returns `undefined` if the source is missing or malformed.\n * @internal\n */\nfunction extractDidAddress(source: string | undefined): Address | undefined {\n if (!source) return undefined;\n const match = /^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/.exec(source);\n return match ? (match[1] as Address) : undefined;\n}\n\n/** @internal */\nclass MismatchError extends Error {\n override readonly name = \"MismatchError\";\n\n constructor(reason: string, details: Record<string, string>) {\n super(\n [\n reason,\n ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`),\n ].join(\"\\n\")\n );\n }\n}\n","export const chainId = {\n mainnet: 16661,\n testnet: 16602,\n} as const;\n\nexport type ChainId = (typeof chainId)[keyof typeof chainId];\n\nconst USDC_E = \"0x1f3aa82227281ca364bfb3d253b0f1af1da6473e\";\n\n/** Chain ID → default currency. */\nexport const currency: Partial<Record<ChainId, string>> = {\n [chainId.mainnet]: USDC_E,\n};\n\n/** Default token decimals for USDC.e. */\nexport const decimals = 6;\n\n/** Default RPC URLs per chain. */\nexport const rpcUrl: Record<number, string> = {\n [chainId.mainnet]: \"https://evmrpc.0g.ai\",\n [chainId.testnet]: \"https://evmrpc-testnet.0g.ai\",\n};\n\n/** ERC-3009 ABI (`transferWithAuthorization`, `receiveWithAuthorization`). */\nexport const erc3009Abi = [\n {\n type: \"function\",\n name: \"transferWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"receiveWithAuthorization\",\n inputs: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n { name: \"v\", type: \"uint8\" },\n { name: \"r\", type: \"bytes32\" },\n { name: \"s\", type: \"bytes32\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"name\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"version\",\n inputs: [],\n outputs: [{ name: \"\", type: \"string\" }],\n stateMutability: \"view\",\n },\n] as const;\n\n/**\n * Known tokens that support ERC-3009 (TransferWithAuthorization).\n * Keyed by lowercase address for case-insensitive lookup.\n */\nexport const erc3009Tokens: Record<string, { name: string; version: string }> =\n {\n [USDC_E.toLowerCase()]: {\n name: \"Bridged USDC\",\n version: \"2\",\n },\n };\n\n/** Resolves the default currency for a given chain. */\nexport function resolveCurrency(parameters: {\n chainId?: number | undefined;\n testnet?: boolean | undefined;\n}): string {\n const id =\n parameters.chainId ??\n (parameters.testnet ? chainId.testnet : chainId.mainnet);\n const resolved = currency[id as ChainId];\n if (!resolved)\n throw new Error(`No default currency configured for chainId ${id}.`);\n return resolved;\n}\n","import { Method, z } from \"mppx\";\nimport { parseUnits } from \"viem\";\n\n/**\n * 0G charge intent for one-time ERC-20 token transfers.\n */\nexport const charge = Method.from({\n name: \"zerog\",\n intent: \"charge\",\n schema: {\n credential: {\n payload: z.discriminatedUnion(\"type\", [\n z.object({ hash: z.hash(), type: z.literal(\"hash\") }),\n z.object({\n type: z.literal(\"authorization\"),\n from: z.string(),\n to: z.string(),\n value: z.string(),\n validAfter: z.string(),\n validBefore: z.string(),\n nonce: z.string(),\n signature: z.string(),\n }),\n ]),\n },\n request: z.pipe(\n z.object({\n amount: z.amount(),\n chainId: z.optional(z.number()),\n currency: z.string(),\n decimals: z.number(),\n description: z.optional(z.string()),\n externalId: z.optional(z.string()),\n recipient: z.optional(z.string()),\n }),\n z.transform(({ amount, chainId, decimals, ...rest }) => ({\n ...rest,\n amount: parseUnits(amount, decimals).toString(),\n ...(chainId !== undefined ? { methodDetails: { chainId } } : {}),\n }))\n ),\n },\n});\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` server method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/server\";\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ recipient: \"0x...\", currency: \"0x...\" })],\n * });\n * ```\n */\nexport function zerog(\n parameters?: zerog.Parameters\n): readonly [Method.AnyServer] {\n return [zerog.charge(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","import_mppx","import_viem","chainId","decimals","charge","currency","decimals","chainId","zerog","charge"]}
@@ -11,7 +11,7 @@ import {
11
11
  import { Credential, Method, z } from "mppx";
12
12
  import { encodeFunctionData, erc20Abi } from "viem";
13
13
  import { parseAccount } from "viem/accounts";
14
- import { sendTransactionSync, signTypedData } from "viem/actions";
14
+ import { sendTransaction, signTypedData } from "viem/actions";
15
15
  function charge2(parameters = {}) {
16
16
  const resolveAccount = (client, override) => {
17
17
  const raw = override ?? parameters.account;
@@ -101,7 +101,7 @@ function charge2(parameters = {}) {
101
101
  });
102
102
  }
103
103
  if (mode === "push") {
104
- const receipt = await sendTransactionSync(client, {
104
+ const hash = await sendTransaction(client, {
105
105
  account,
106
106
  chain: client.chain,
107
107
  to: currency,
@@ -111,7 +111,6 @@ function charge2(parameters = {}) {
111
111
  args: [recipient, amount]
112
112
  })
113
113
  });
114
- const hash = receipt.transactionHash;
115
114
  return Credential.serialize({
116
115
  challenge,
117
116
  payload: { hash, type: "hash" },
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/Charge.ts","../../src/client/Methods.ts"],"sourcesContent":["import type { Account, Address, Chain, Client } from \"viem\";\nimport { Credential, Method, z } from \"mppx\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { sendTransactionSync, signTypedData } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the client.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const charge = zerog.charge({\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}) {\n const resolveAccount = (\n client: Client,\n override?: Account | Address | undefined\n ): Account => {\n const raw = override ?? parameters.account;\n if (raw) return typeof raw === \"string\" ? parseAccount(raw) : raw;\n if (client.account) return client.account;\n throw new Error(\n \"No `account` provided. Pass `account` to parameters or context.\"\n );\n };\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toClient(Methods.charge, {\n context: z.object({\n account: z.optional(z.custom<Account | Address>()),\n mode: z.optional(z.enum([\"push\", \"pull\"])),\n }),\n\n async createCredential({ challenge, context }) {\n const chainId = challenge.request.methodDetails?.chainId as\n | number\n | undefined;\n const client = await resolveClient(chainId);\n const account = resolveAccount(client, context?.account);\n\n const mode =\n context?.mode ??\n parameters.mode ??\n (account.type === \"json-rpc\" ? \"push\" : \"pull\");\n\n const { request } = challenge;\n const amount = BigInt(request.amount);\n const currency = request.currency as Address;\n const recipient = request.recipient as Address;\n\n if (mode === \"pull\") {\n const tokenMeta = defaults.erc3009Tokens[currency.toLowerCase()];\n if (!tokenMeta) {\n throw new Error(\n `Token ${currency} does not support ERC-3009 (TransferWithAuthorization). ` +\n `Cannot use pull mode.`\n );\n }\n\n const resolvedChainId = chainId ?? client.chain?.id;\n if (!resolvedChainId)\n throw new Error(\"Could not determine chainId for EIP-712 domain.\");\n\n const { name: tokenName, version: tokenVersion } = tokenMeta;\n\n const validAfter = 0n;\n const validBefore = challenge.expires\n ? BigInt(Math.floor(new Date(challenge.expires).getTime() / 1000))\n : BigInt(Math.floor(Date.now() / 1000) + 3600); // 1 hour default\n const nonce = randomNonce();\n\n const signature = await signTypedData(client, {\n account,\n domain: {\n name: tokenName,\n version: tokenVersion,\n chainId: resolvedChainId,\n verifyingContract: currency,\n },\n types: {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n },\n primaryType: \"TransferWithAuthorization\",\n message: {\n from: account.address,\n to: recipient,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n },\n });\n\n return Credential.serialize({\n challenge,\n payload: {\n type: \"authorization\" as const,\n from: account.address,\n to: recipient,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n signature,\n },\n source: `did:pkh:eip155:${resolvedChainId}:${account.address}`,\n });\n }\n\n if (mode === \"push\") {\n const receipt = await sendTransactionSync(client, {\n account,\n chain: client.chain,\n to: currency,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [recipient, amount],\n }),\n });\n const hash = receipt.transactionHash;\n return Credential.serialize({\n challenge,\n payload: { hash, type: \"hash\" },\n source: `did:pkh:eip155:${chainId ?? client.chain?.id}:${account.address}`,\n });\n }\n\n throw new Error(`Unsupported mode: ${mode}`);\n },\n });\n}\n\nexport declare namespace charge {\n type Parameters = {\n /** Account to use for signing. */\n account?: Account | Address | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Controls how the charge transaction is submitted.\n *\n * - `'push'`: Client broadcasts the transaction and sends the tx hash.\n * - `'pull'`: Client signs an ERC-3009 TransferWithAuthorization\n * message. Server calls `transferWithAuthorization` and pays gas.\n *\n * @default `'push'` for JSON-RPC accounts, `'pull'` for local accounts.\n */\n mode?: \"push\" | \"pull\" | undefined;\n };\n}\n\n/** Generates a random 32-byte hex nonce. */\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n if (typeof crypto !== \"undefined\") {\n crypto.getRandomValues(bytes);\n } else if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n (globalThis as unknown as { crypto: Crypto }).crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return `0x${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` client method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/client\";\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ account })],\n * });\n * ```\n */\nexport function zerog(\n parameters: zerog.Parameters = {}\n): readonly [Method.AnyClient] {\n return [charge_(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` client method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","chainId","charge","zerog"]}
1
+ {"version":3,"sources":["../../src/client/Charge.ts","../../src/client/Methods.ts"],"sourcesContent":["import type { Account, Address, Chain, Client } from \"viem\";\nimport { Credential, Method, z } from \"mppx\";\nimport { encodeFunctionData, erc20Abi } from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { sendTransaction, signTypedData } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the client.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n * import { privateKeyToAccount } from \"viem/accounts\";\n *\n * const charge = zerog.charge({\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}) {\n const resolveAccount = (\n client: Client,\n override?: Account | Address | undefined\n ): Account => {\n const raw = override ?? parameters.account;\n if (raw) return typeof raw === \"string\" ? parseAccount(raw) : raw;\n if (client.account) return client.account;\n throw new Error(\n \"No `account` provided. Pass `account` to parameters or context.\"\n );\n };\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toClient(Methods.charge, {\n context: z.object({\n account: z.optional(z.custom<Account | Address>()),\n mode: z.optional(z.enum([\"push\", \"pull\"])),\n }),\n\n async createCredential({ challenge, context }) {\n const chainId = challenge.request.methodDetails?.chainId as\n | number\n | undefined;\n const client = await resolveClient(chainId);\n const account = resolveAccount(client, context?.account);\n\n const mode =\n context?.mode ??\n parameters.mode ??\n (account.type === \"json-rpc\" ? \"push\" : \"pull\");\n\n const { request } = challenge;\n const amount = BigInt(request.amount);\n const currency = request.currency as Address;\n const recipient = request.recipient as Address;\n\n if (mode === \"pull\") {\n const tokenMeta = defaults.erc3009Tokens[currency.toLowerCase()];\n if (!tokenMeta) {\n throw new Error(\n `Token ${currency} does not support ERC-3009 (TransferWithAuthorization). ` +\n `Cannot use pull mode.`\n );\n }\n\n const resolvedChainId = chainId ?? client.chain?.id;\n if (!resolvedChainId)\n throw new Error(\"Could not determine chainId for EIP-712 domain.\");\n\n const { name: tokenName, version: tokenVersion } = tokenMeta;\n\n const validAfter = 0n;\n const validBefore = challenge.expires\n ? BigInt(Math.floor(new Date(challenge.expires).getTime() / 1000))\n : BigInt(Math.floor(Date.now() / 1000) + 3600); // 1 hour default\n const nonce = randomNonce();\n\n const signature = await signTypedData(client, {\n account,\n domain: {\n name: tokenName,\n version: tokenVersion,\n chainId: resolvedChainId,\n verifyingContract: currency,\n },\n types: {\n TransferWithAuthorization: [\n { name: \"from\", type: \"address\" },\n { name: \"to\", type: \"address\" },\n { name: \"value\", type: \"uint256\" },\n { name: \"validAfter\", type: \"uint256\" },\n { name: \"validBefore\", type: \"uint256\" },\n { name: \"nonce\", type: \"bytes32\" },\n ],\n },\n primaryType: \"TransferWithAuthorization\",\n message: {\n from: account.address,\n to: recipient,\n value: amount,\n validAfter,\n validBefore,\n nonce,\n },\n });\n\n return Credential.serialize({\n challenge,\n payload: {\n type: \"authorization\" as const,\n from: account.address,\n to: recipient,\n value: amount.toString(),\n validAfter: validAfter.toString(),\n validBefore: validBefore.toString(),\n nonce,\n signature,\n },\n source: `did:pkh:eip155:${resolvedChainId}:${account.address}`,\n });\n }\n\n if (mode === \"push\") {\n const hash = await sendTransaction(client, {\n account,\n chain: client.chain,\n to: currency,\n data: encodeFunctionData({\n abi: erc20Abi,\n functionName: \"transfer\",\n args: [recipient, amount] as const,\n }),\n });\n\n return Credential.serialize({\n challenge,\n payload: { hash, type: \"hash\" },\n source: `did:pkh:eip155:${chainId ?? client.chain?.id}:${account.address}`,\n });\n }\n\n throw new Error(`Unsupported mode: ${mode}`);\n },\n });\n}\n\nexport declare namespace charge {\n type Parameters = {\n /** Account to use for signing. */\n account?: Account | Address | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Controls how the charge transaction is submitted.\n *\n * - `'push'`: Client broadcasts the transaction and sends the tx hash.\n * - `'pull'`: Client signs an ERC-3009 TransferWithAuthorization\n * message. Server calls `transferWithAuthorization` and pays gas.\n *\n * @default `'push'` for JSON-RPC accounts, `'pull'` for local accounts.\n */\n mode?: \"push\" | \"pull\" | undefined;\n };\n}\n\n/** Generates a random 32-byte hex nonce. */\nfunction randomNonce(): `0x${string}` {\n const bytes = new Uint8Array(32);\n if (typeof crypto !== \"undefined\") {\n crypto.getRandomValues(bytes);\n } else if (typeof globalThis !== \"undefined\" && \"crypto\" in globalThis) {\n (globalThis as unknown as { crypto: Crypto }).crypto.getRandomValues(bytes);\n } else {\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n return `0x${[...bytes].map((b) => b.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` client method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/client\";\n * import { zerog } from \"@heraldprotocol/mpp/client\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ account })],\n * });\n * ```\n */\nexport function zerog(\n parameters: zerog.Parameters = {}\n): readonly [Method.AnyClient] {\n return [charge_(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` client method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","chainId","charge","zerog"]}
@@ -20,11 +20,7 @@ import {
20
20
  parseEventLogs
21
21
  } from "viem";
22
22
  import { parseAccount } from "viem/accounts";
23
- import {
24
- getTransactionReceipt,
25
- sendTransaction,
26
- sendTransactionSync
27
- } from "viem/actions";
23
+ import { getTransactionReceipt, sendTransaction } from "viem/actions";
28
24
  function charge2(parameters = {}) {
29
25
  const {
30
26
  amount,
@@ -146,33 +142,10 @@ function charge2(parameters = {}) {
146
142
  `ERC-3009 authorization expired (validBefore: ${validBefore}).`
147
143
  );
148
144
  }
149
- const hash = keccak256(signature);
150
- await assertHashUnused(store, hash);
151
- await markHashUsed(store, hash);
152
- if (waitForConfirmation) {
153
- const receipt = await sendTransactionSync(client, {
154
- account: serverAccount,
155
- chain: client.chain,
156
- to: challengeCurrency,
157
- data: encodeFunctionData({
158
- abi: erc3009Abi,
159
- functionName: "transferWithAuthorization",
160
- args: [
161
- from,
162
- to,
163
- BigInt(value),
164
- BigInt(validAfter),
165
- BigInt(validBefore),
166
- nonce,
167
- v,
168
- r,
169
- s
170
- ]
171
- })
172
- });
173
- return toReceipt(receipt);
174
- }
175
- const txHash = await sendTransaction(client, {
145
+ const signatureHash = keccak256(signature);
146
+ await assertHashUnused(store, signatureHash);
147
+ await markHashUsed(store, signatureHash);
148
+ const hash = await sendTransaction(client, {
176
149
  account: serverAccount,
177
150
  chain: client.chain,
178
151
  to: challengeCurrency,
@@ -192,11 +165,17 @@ function charge2(parameters = {}) {
192
165
  ]
193
166
  })
194
167
  });
168
+ if (waitForConfirmation) {
169
+ const receipt = await getTransactionReceipt(client, {
170
+ hash
171
+ });
172
+ return toReceipt(receipt);
173
+ }
195
174
  return {
196
175
  method: "zerog",
197
176
  status: "success",
198
177
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
199
- reference: txHash
178
+ reference: hash
200
179
  };
201
180
  }
202
181
  default:
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/server/Charge.ts","../../src/server/Methods.ts"],"sourcesContent":["import type { Account, Address, Chain, Client, TransactionReceipt } from \"viem\";\nimport { Method, Store } from \"mppx\";\nimport {\n encodeFunctionData,\n erc20Abi,\n isAddressEqual,\n keccak256,\n parseEventLogs,\n} from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport {\n getTransactionReceipt,\n sendTransaction,\n sendTransactionSync,\n} from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the server.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const charge = zerog.charge({\n * recipient: \"0x...\",\n * currency: \"0x...\",\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}): Method.AnyServer {\n const {\n amount,\n currency = defaults.resolveCurrency(parameters),\n decimals = defaults.decimals,\n description,\n externalId,\n recipient,\n waitForConfirmation = true,\n } = parameters;\n const store = (parameters.store ??\n Store.memory()) as Store.Store<charge.StoreItemMap>;\n\n if (currency.toLowerCase() in defaults.erc3009Tokens && !parameters.account) {\n throw new Error(\n \"ERC-3009 requires an `account` parameter so the server can sign and broadcast \" +\n \"the transferWithAuthorization transaction.\"\n );\n }\n\n const serverAccount = parameters.account\n ? typeof parameters.account === \"string\"\n ? parseAccount(parameters.account)\n : parameters.account\n : undefined;\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toServer(Methods.charge, {\n defaults: {\n amount,\n currency,\n decimals,\n description,\n externalId,\n recipient,\n } as never,\n\n async request({ request }) {\n const chainId = await (async () => {\n if (request.chainId) return request.chainId;\n if (parameters.testnet) return defaults.chainId.testnet;\n return (await resolveClient(undefined)).chain?.id;\n })();\n\n const client = await (async () => {\n try {\n return await resolveClient(chainId);\n } catch {\n throw new Error(`No client configured with chainId ${chainId}.`);\n }\n })();\n if (client.chain?.id !== chainId)\n throw new Error(`Client not configured with chainId ${chainId}.`);\n\n return { ...request, chainId };\n },\n\n async verify({ credential, request }) {\n const { challenge } = credential;\n const { chainId } = request;\n\n const client = await resolveClient(chainId);\n\n const { request: challengeRequest } = challenge;\n const challengeAmount = challengeRequest.amount as string;\n const challengeCurrency = challengeRequest.currency as Address;\n const challengeRecipient = challengeRequest.recipient as Address;\n const expires = challenge.expires;\n\n if (expires && new Date(expires) < new Date()) {\n throw new Error(`Payment expired at ${expires}.`);\n }\n\n const payload = credential.payload;\n\n switch (payload.type) {\n case \"hash\": {\n const hash = payload.hash as `0x${string}`;\n await assertHashUnused(store, hash);\n\n const sender = extractDidAddress(credential.source);\n if (!sender)\n throw new Error(\n \"Hash credential is missing a valid `source` DID — cannot verify sender.\"\n );\n\n const receipt = await getTransactionReceipt(client, { hash });\n\n const transferLogs = parseEventLogs({\n abi: erc20Abi,\n eventName: \"Transfer\",\n logs: receipt.logs,\n });\n\n const match = transferLogs.find(\n (log) =>\n isAddressEqual(log.address, challengeCurrency) &&\n isAddressEqual(log.args.from, sender) &&\n isAddressEqual(log.args.to, challengeRecipient) &&\n log.args.value.toString() === challengeAmount\n );\n\n if (!match)\n throw new MismatchError(\n \"Payment verification failed: no matching ERC-20 transfer found.\",\n {\n sender,\n amount: challengeAmount,\n currency: challengeCurrency,\n recipient: challengeRecipient,\n }\n );\n\n await markHashUsed(store, hash);\n\n return toReceipt(receipt);\n }\n\n case \"authorization\": {\n if (!serverAccount) {\n throw new Error(\n \"Received ERC-3009 authorization credential but no server `account` is configured. \" +\n \"Set `account` in charge parameters to broadcast transferWithAuthorization.\"\n );\n }\n\n const { from, to, value, validAfter, validBefore, nonce, signature } =\n payload as {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n signature: string;\n };\n\n // Split signature into v, r, s for the contract call\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Validate authorization parameters match the challenge\n if (!isAddressEqual(to as Address, challengeRecipient))\n throw new MismatchError(\n \"Authorization recipient does not match challenge.\",\n { expected: challengeRecipient, actual: to }\n );\n\n if (value !== challengeAmount)\n throw new MismatchError(\n \"Authorization amount does not match challenge.\",\n { expected: challengeAmount, actual: value }\n );\n\n // Check expiry from the authorization itself\n const validBeforeTs = Number(validBefore);\n if (\n validBeforeTs > 0 &&\n validBeforeTs < Math.floor(Date.now() / 1000)\n ) {\n throw new Error(\n `ERC-3009 authorization expired (validBefore: ${validBefore}).`\n );\n }\n\n const hash = keccak256(signature as `0x${string}`);\n await assertHashUnused(store, hash);\n await markHashUsed(store, hash);\n\n if (waitForConfirmation) {\n const receipt = await sendTransactionSync(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return toReceipt(receipt);\n }\n\n const txHash = await sendTransaction(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: txHash,\n };\n }\n\n default:\n throw new Error(\n `Unsupported credential type \"${(payload as { type: string }).type}\".`\n );\n }\n },\n });\n}\n\nexport declare namespace charge {\n type StoreItemMap = {\n [key: `mppx:charge:${string}`]: number;\n };\n\n type Parameters = {\n /** Default payment amount (human-readable, e.g. \"1.50\"). */\n amount?: string | undefined;\n /** ERC-20 token contract address. */\n currency?: string | undefined;\n /** Token decimals. @default 6 */\n decimals?: number | undefined;\n /** Human-readable description. */\n description?: string | undefined;\n /** External identifier to echo back in receipt. */\n externalId?: string | undefined;\n /** Recipient address for payments. */\n recipient?: string | undefined;\n /** Testnet mode. */\n testnet?: boolean | undefined;\n /**\n * Whether to wait for the charge transaction to confirm on-chain.\n * @default true\n */\n waitForConfirmation?: boolean | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Server account used to broadcast `transferWithAuthorization` transactions.\n * Required when accepting `authorization` payloads. The server pays gas\n * from this account.\n */\n account?: Account | Address | undefined;\n /**\n * Store for transaction hash replay protection.\n *\n * Use a shared store in multi-instance deployments so consumed hashes are\n * visible across all server instances.\n */\n store?: Store.Store | undefined;\n };\n}\n\n/** @internal */\nfunction getHashStoreKey(hash: `0x${string}`): `mppx:charge:${string}` {\n return `mppx:charge:${hash.toLowerCase()}`;\n}\n\n/** @internal */\nasync function assertHashUnused(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n const seen = await store.get(getHashStoreKey(hash));\n if (seen !== null) throw new Error(\"Transaction hash has already been used.\");\n}\n\n/** @internal */\nasync function markHashUsed(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n await store.put(getHashStoreKey(hash), Date.now());\n}\n\n/** @internal */\nfunction toReceipt(receipt: TransactionReceipt) {\n const { status, transactionHash } = receipt;\n if (status !== \"success\") {\n throw new Error(`Transaction reverted: ${transactionHash}`);\n }\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: transactionHash,\n };\n}\n\n/**\n * Extracts an Ethereum address from a `did:pkh:eip155:<chainId>:<address>` DID.\n * Returns `undefined` if the source is missing or malformed.\n * @internal\n */\nfunction extractDidAddress(source: string | undefined): Address | undefined {\n if (!source) return undefined;\n const match = /^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/.exec(source);\n return match ? (match[1] as Address) : undefined;\n}\n\n/** @internal */\nclass MismatchError extends Error {\n override readonly name = \"MismatchError\";\n\n constructor(reason: string, details: Record<string, string>) {\n super(\n [\n reason,\n ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`),\n ].join(\"\\n\")\n );\n }\n}\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` server method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/server\";\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ recipient: \"0x...\", currency: \"0x...\" })],\n * });\n * ```\n */\nexport function zerog(\n parameters?: zerog.Parameters\n): readonly [Method.AnyServer] {\n return [zerog.charge(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","decimals","chainId","zerog","charge"]}
1
+ {"version":3,"sources":["../../src/server/Charge.ts","../../src/server/Methods.ts"],"sourcesContent":["import type { Account, Address, Chain, Client, TransactionReceipt } from \"viem\";\nimport { Method, Store } from \"mppx\";\nimport {\n encodeFunctionData,\n erc20Abi,\n isAddressEqual,\n keccak256,\n parseEventLogs,\n} from \"viem\";\nimport { parseAccount } from \"viem/accounts\";\nimport { getTransactionReceipt, sendTransaction } from \"viem/actions\";\n\nimport type { MaybePromise } from \"../types.js\";\nimport * as defaults from \"../defaults.js\";\nimport * as Methods from \"../Methods.js\";\n\n/**\n * Creates a 0G charge method intent for usage on the server.\n *\n * @example\n * ```ts\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const charge = zerog.charge({\n * recipient: \"0x...\",\n * currency: \"0x...\",\n * account: privateKeyToAccount(\"0x...\"),\n * });\n * ```\n */\nexport function charge(parameters: charge.Parameters = {}): Method.AnyServer {\n const {\n amount,\n currency = defaults.resolveCurrency(parameters),\n decimals = defaults.decimals,\n description,\n externalId,\n recipient,\n waitForConfirmation = true,\n } = parameters;\n const store = (parameters.store ??\n Store.memory()) as Store.Store<charge.StoreItemMap>;\n\n if (currency.toLowerCase() in defaults.erc3009Tokens && !parameters.account) {\n throw new Error(\n \"ERC-3009 requires an `account` parameter so the server can sign and broadcast \" +\n \"the transferWithAuthorization transaction.\"\n );\n }\n\n const serverAccount = parameters.account\n ? typeof parameters.account === \"string\"\n ? parseAccount(parameters.account)\n : parameters.account\n : undefined;\n\n const resolveClient = async (\n chainId?: number | undefined\n ): Promise<Client> => {\n if (parameters.getClient) return parameters.getClient({ chainId });\n const id = chainId ?? defaults.chainId.mainnet;\n const url = defaults.rpcUrl[id];\n if (!url) throw new Error(`No RPC URL configured for chainId ${id}.`);\n const { createClient, http } = await import(\"viem\");\n return createClient({ chain: { id } as Chain, transport: http(url) });\n };\n\n return Method.toServer(Methods.charge, {\n defaults: {\n amount,\n currency,\n decimals,\n description,\n externalId,\n recipient,\n } as never,\n\n async request({ request }) {\n const chainId = await (async () => {\n if (request.chainId) return request.chainId;\n if (parameters.testnet) return defaults.chainId.testnet;\n return (await resolveClient(undefined)).chain?.id;\n })();\n\n const client = await (async () => {\n try {\n return await resolveClient(chainId);\n } catch {\n throw new Error(`No client configured with chainId ${chainId}.`);\n }\n })();\n if (client.chain?.id !== chainId)\n throw new Error(`Client not configured with chainId ${chainId}.`);\n\n return { ...request, chainId };\n },\n\n async verify({ credential, request }) {\n const { challenge } = credential;\n const { chainId } = request;\n\n const client = await resolveClient(chainId);\n\n const { request: challengeRequest } = challenge;\n const challengeAmount = challengeRequest.amount as string;\n const challengeCurrency = challengeRequest.currency as Address;\n const challengeRecipient = challengeRequest.recipient as Address;\n const expires = challenge.expires;\n\n if (expires && new Date(expires) < new Date()) {\n throw new Error(`Payment expired at ${expires}.`);\n }\n\n const payload = credential.payload;\n\n switch (payload.type) {\n case \"hash\": {\n const hash = payload.hash as `0x${string}`;\n await assertHashUnused(store, hash);\n\n const sender = extractDidAddress(credential.source);\n if (!sender)\n throw new Error(\n \"Hash credential is missing a valid `source` DID — cannot verify sender.\"\n );\n\n const receipt = await getTransactionReceipt(client, { hash });\n\n const transferLogs = parseEventLogs({\n abi: erc20Abi,\n eventName: \"Transfer\",\n logs: receipt.logs,\n });\n\n const match = transferLogs.find(\n (log) =>\n isAddressEqual(log.address, challengeCurrency) &&\n isAddressEqual(log.args.from, sender) &&\n isAddressEqual(log.args.to, challengeRecipient) &&\n log.args.value.toString() === challengeAmount\n );\n\n if (!match)\n throw new MismatchError(\n \"Payment verification failed: no matching ERC-20 transfer found.\",\n {\n sender,\n amount: challengeAmount,\n currency: challengeCurrency,\n recipient: challengeRecipient,\n }\n );\n\n await markHashUsed(store, hash);\n\n return toReceipt(receipt);\n }\n\n case \"authorization\": {\n if (!serverAccount) {\n throw new Error(\n \"Received ERC-3009 authorization credential but no server `account` is configured. \" +\n \"Set `account` in charge parameters to broadcast transferWithAuthorization.\"\n );\n }\n\n const { from, to, value, validAfter, validBefore, nonce, signature } =\n payload as {\n from: string;\n to: string;\n value: string;\n validAfter: string;\n validBefore: string;\n nonce: string;\n signature: string;\n };\n\n // Split signature into v, r, s for the contract call\n const r = `0x${signature.slice(2, 66)}` as `0x${string}`;\n const s = `0x${signature.slice(66, 130)}` as `0x${string}`;\n const v = parseInt(signature.slice(130, 132), 16);\n\n // Validate authorization parameters match the challenge\n if (!isAddressEqual(to as Address, challengeRecipient))\n throw new MismatchError(\n \"Authorization recipient does not match challenge.\",\n { expected: challengeRecipient, actual: to }\n );\n\n if (value !== challengeAmount)\n throw new MismatchError(\n \"Authorization amount does not match challenge.\",\n { expected: challengeAmount, actual: value }\n );\n\n // Check expiry from the authorization itself\n const validBeforeTs = Number(validBefore);\n if (\n validBeforeTs > 0 &&\n validBeforeTs < Math.floor(Date.now() / 1000)\n ) {\n throw new Error(\n `ERC-3009 authorization expired (validBefore: ${validBefore}).`\n );\n }\n\n const signatureHash = keccak256(signature as `0x${string}`);\n await assertHashUnused(store, signatureHash);\n await markHashUsed(store, signatureHash);\n\n const hash = await sendTransaction(client, {\n account: serverAccount,\n chain: client.chain,\n to: challengeCurrency,\n data: encodeFunctionData({\n abi: defaults.erc3009Abi,\n functionName: \"transferWithAuthorization\",\n args: [\n from as Address,\n to as Address,\n BigInt(value),\n BigInt(validAfter),\n BigInt(validBefore),\n nonce as `0x${string}`,\n v,\n r as `0x${string}`,\n s as `0x${string}`,\n ],\n }),\n } as never);\n\n if (waitForConfirmation) {\n const receipt = await getTransactionReceipt(client, {\n hash,\n });\n\n return toReceipt(receipt);\n }\n\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: hash,\n };\n }\n\n default:\n throw new Error(\n `Unsupported credential type \"${(payload as { type: string }).type}\".`\n );\n }\n },\n });\n}\n\nexport declare namespace charge {\n type StoreItemMap = {\n [key: `mppx:charge:${string}`]: number;\n };\n\n type Parameters = {\n /** Default payment amount (human-readable, e.g. \"1.50\"). */\n amount?: string | undefined;\n /** ERC-20 token contract address. */\n currency?: string | undefined;\n /** Token decimals. @default 6 */\n decimals?: number | undefined;\n /** Human-readable description. */\n description?: string | undefined;\n /** External identifier to echo back in receipt. */\n externalId?: string | undefined;\n /** Recipient address for payments. */\n recipient?: string | undefined;\n /** Testnet mode. */\n testnet?: boolean | undefined;\n /**\n * Whether to wait for the charge transaction to confirm on-chain.\n * @default true\n */\n waitForConfirmation?: boolean | undefined;\n /** Function that returns a viem Client for the given chain ID. */\n getClient?:\n | ((parameters: { chainId?: number | undefined }) => MaybePromise<Client>)\n | undefined;\n /**\n * Server account used to broadcast `transferWithAuthorization` transactions.\n * Required when accepting `authorization` payloads. The server pays gas\n * from this account.\n */\n account?: Account | Address | undefined;\n /**\n * Store for transaction hash replay protection.\n *\n * Use a shared store in multi-instance deployments so consumed hashes are\n * visible across all server instances.\n */\n store?: Store.Store | undefined;\n };\n}\n\n/** @internal */\nfunction getHashStoreKey(hash: `0x${string}`): `mppx:charge:${string}` {\n return `mppx:charge:${hash.toLowerCase()}`;\n}\n\n/** @internal */\nasync function assertHashUnused(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n const seen = await store.get(getHashStoreKey(hash));\n if (seen !== null) throw new Error(\"Transaction hash has already been used.\");\n}\n\n/** @internal */\nasync function markHashUsed(\n store: Store.Store<charge.StoreItemMap>,\n hash: `0x${string}`\n): Promise<void> {\n await store.put(getHashStoreKey(hash), Date.now());\n}\n\n/** @internal */\nfunction toReceipt(receipt: TransactionReceipt) {\n const { status, transactionHash } = receipt;\n if (status !== \"success\") {\n throw new Error(`Transaction reverted: ${transactionHash}`);\n }\n return {\n method: \"zerog\" as const,\n status: \"success\" as const,\n timestamp: new Date().toISOString(),\n reference: transactionHash,\n };\n}\n\n/**\n * Extracts an Ethereum address from a `did:pkh:eip155:<chainId>:<address>` DID.\n * Returns `undefined` if the source is missing or malformed.\n * @internal\n */\nfunction extractDidAddress(source: string | undefined): Address | undefined {\n if (!source) return undefined;\n const match = /^did:pkh:eip155:\\d+:(0x[0-9a-fA-F]{40})$/.exec(source);\n return match ? (match[1] as Address) : undefined;\n}\n\n/** @internal */\nclass MismatchError extends Error {\n override readonly name = \"MismatchError\";\n\n constructor(reason: string, details: Record<string, string>) {\n super(\n [\n reason,\n ...Object.entries(details).map(([k, v]) => ` - ${k}: ${v}`),\n ].join(\"\\n\")\n );\n }\n}\n","import type { Method } from \"mppx\";\n\nimport { charge as charge_ } from \"./Charge.js\";\n\n/**\n * Creates a 0G `charge` server method.\n *\n * @example\n * ```ts\n * import { Mppx } from \"mppx/server\";\n * import { zerog } from \"@heraldprotocol/mpp/server\";\n *\n * const mppx = Mppx.create({\n * methods: [zerog({ recipient: \"0x...\", currency: \"0x...\" })],\n * });\n * ```\n */\nexport function zerog(\n parameters?: zerog.Parameters\n): readonly [Method.AnyServer] {\n return [zerog.charge(parameters)] as const;\n}\n\nexport namespace zerog {\n export type Parameters = charge_.Parameters;\n\n /** Creates a 0G `charge` method for one-time ERC-20 token transfers. */\n export const charge = charge_;\n}\n"],"mappings":"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","names":["charge","decimals","chainId","zerog","charge"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@heraldprotocol/mpp",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "description": "0G Chain payment method for the Machine Payments Protocol",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,16 +14,34 @@
14
14
  "type": "module",
15
15
  "exports": {
16
16
  ".": {
17
- "types": "./dist/esm/index.d.ts",
18
- "default": "./dist/esm/index.js"
19
- },
20
- "./client": {
21
- "types": "./dist/esm/client/index.d.ts",
22
- "default": "./dist/esm/client/index.js"
17
+ "import": {
18
+ "types": "./dist/esm/index.d.ts",
19
+ "default": "./dist/esm/index.js"
20
+ },
21
+ "require": {
22
+ "types": "./dist/cjs/index.d.ts",
23
+ "default": "./dist/cjs/index.js"
24
+ }
23
25
  },
24
26
  "./server": {
25
- "types": "./dist/esm/server/index.d.ts",
26
- "default": "./dist/esm/server/index.js"
27
+ "import": {
28
+ "types": "./dist/esm/server.d.ts",
29
+ "default": "./dist/esm/server.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/cjs/server.d.ts",
33
+ "default": "./dist/cjs/server.js"
34
+ }
35
+ },
36
+ "./client": {
37
+ "import": {
38
+ "types": "./dist/esm/client.d.ts",
39
+ "default": "./dist/esm/client.js"
40
+ },
41
+ "require": {
42
+ "types": "./dist/cjs/client.d.ts",
43
+ "default": "./dist/cjs/client.js"
44
+ }
27
45
  }
28
46
  },
29
47
  "main": "./dist/esm/index.js",