@x402/aptos 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -0
- package/dist/cjs/exact/client/index.d.ts +29 -0
- package/dist/cjs/exact/client/index.js +141 -0
- package/dist/cjs/exact/client/index.js.map +1 -0
- package/dist/cjs/exact/facilitator/index.d.ts +52 -0
- package/dist/cjs/exact/facilitator/index.js +373 -0
- package/dist/cjs/exact/facilitator/index.js.map +1 -0
- package/dist/cjs/exact/server/index.d.ts +67 -0
- package/dist/cjs/exact/server/index.js +143 -0
- package/dist/cjs/exact/server/index.js.map +1 -0
- package/dist/cjs/index.d.ts +116 -0
- package/dist/cjs/index.js +269 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/signer-DPT9P1NX.d.ts +59 -0
- package/dist/cjs/signer-DfwN1I5I.d.ts +59 -0
- package/dist/esm/chunk-6BMAMLXJ.mjs +93 -0
- package/dist/esm/chunk-6BMAMLXJ.mjs.map +1 -0
- package/dist/esm/chunk-D4UVBSUH.mjs +53 -0
- package/dist/esm/chunk-D4UVBSUH.mjs.map +1 -0
- package/dist/esm/chunk-FG4ANPDN.mjs +46 -0
- package/dist/esm/chunk-FG4ANPDN.mjs.map +1 -0
- package/dist/esm/exact/client/index.d.mts +29 -0
- package/dist/esm/exact/client/index.mjs +9 -0
- package/dist/esm/exact/client/index.mjs.map +1 -0
- package/dist/esm/exact/facilitator/index.d.mts +52 -0
- package/dist/esm/exact/facilitator/index.mjs +294 -0
- package/dist/esm/exact/facilitator/index.mjs.map +1 -0
- package/dist/esm/exact/server/index.d.mts +67 -0
- package/dist/esm/exact/server/index.mjs +116 -0
- package/dist/esm/exact/server/index.mjs.map +1 -0
- package/dist/esm/index.d.mts +116 -0
- package/dist/esm/index.mjs +105 -0
- package/dist/esm/index.mjs.map +1 -0
- package/dist/esm/signer-DPT9P1NX.d.mts +59 -0
- package/package.json +95 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAptosNetwork,
|
|
3
|
+
getAptosRpcUrl
|
|
4
|
+
} from "./chunk-FG4ANPDN.mjs";
|
|
5
|
+
|
|
6
|
+
// src/utils.ts
|
|
7
|
+
import {
|
|
8
|
+
Deserializer,
|
|
9
|
+
SimpleTransaction,
|
|
10
|
+
AccountAuthenticator,
|
|
11
|
+
Aptos,
|
|
12
|
+
AptosConfig
|
|
13
|
+
} from "@aptos-labs/ts-sdk";
|
|
14
|
+
function deserializeAptosPayment(transactionBase64) {
|
|
15
|
+
const decoded = Buffer.from(transactionBase64, "base64").toString("utf8");
|
|
16
|
+
const parsed = JSON.parse(decoded);
|
|
17
|
+
const transactionBytes = Uint8Array.from(parsed.transaction);
|
|
18
|
+
const transaction = SimpleTransaction.deserialize(new Deserializer(transactionBytes));
|
|
19
|
+
const authBytes = Uint8Array.from(parsed.senderAuthenticator);
|
|
20
|
+
const senderAuthenticator = AccountAuthenticator.deserialize(new Deserializer(authBytes));
|
|
21
|
+
if (!isEntryFunctionPayload(transaction.rawTransaction.payload)) {
|
|
22
|
+
return { transaction, senderAuthenticator };
|
|
23
|
+
}
|
|
24
|
+
const entryFunction = transaction.rawTransaction.payload.entryFunction;
|
|
25
|
+
return { transaction, senderAuthenticator, entryFunction };
|
|
26
|
+
}
|
|
27
|
+
function isEntryFunctionPayload(payload) {
|
|
28
|
+
return "entryFunction" in payload;
|
|
29
|
+
}
|
|
30
|
+
function createAptosClient(network, rpcUrl) {
|
|
31
|
+
const aptosNetwork = getAptosNetwork(network);
|
|
32
|
+
const fullnodeUrl = rpcUrl || getAptosRpcUrl(aptosNetwork);
|
|
33
|
+
const config = new AptosConfig({
|
|
34
|
+
network: aptosNetwork,
|
|
35
|
+
fullnode: fullnodeUrl
|
|
36
|
+
});
|
|
37
|
+
return new Aptos(config);
|
|
38
|
+
}
|
|
39
|
+
function encodeAptosPayload(transactionBytes, authenticatorBytes) {
|
|
40
|
+
const payload = {
|
|
41
|
+
transaction: Array.from(transactionBytes),
|
|
42
|
+
senderAuthenticator: Array.from(authenticatorBytes)
|
|
43
|
+
};
|
|
44
|
+
return Buffer.from(JSON.stringify(payload)).toString("base64");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
deserializeAptosPayment,
|
|
49
|
+
isEntryFunctionPayload,
|
|
50
|
+
createAptosClient,
|
|
51
|
+
encodeAptosPayload
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=chunk-D4UVBSUH.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utils.ts"],"sourcesContent":["import {\n Deserializer,\n SimpleTransaction,\n AccountAuthenticator,\n TransactionPayloadEntryFunction,\n TransactionPayload,\n EntryFunction,\n Aptos,\n AptosConfig,\n} from \"@aptos-labs/ts-sdk\";\nimport type { DecodedAptosPayload } from \"./types\";\nimport { getAptosNetwork, getAptosRpcUrl } from \"./constants\";\n\n/**\n * Deserialize an Aptos transaction and authenticator from the payment payload.\n *\n * @param transactionBase64 - The base64 encoded transaction payload\n * @returns The deserialized transaction and authenticator\n */\nexport function deserializeAptosPayment(transactionBase64: string): {\n transaction: SimpleTransaction;\n senderAuthenticator: AccountAuthenticator;\n entryFunction?: EntryFunction;\n} {\n // Decode the base64 payload\n const decoded = Buffer.from(transactionBase64, \"base64\").toString(\"utf8\");\n const parsed: DecodedAptosPayload = JSON.parse(decoded);\n\n // Deserialize the transaction bytes\n const transactionBytes = Uint8Array.from(parsed.transaction);\n const transaction = SimpleTransaction.deserialize(new Deserializer(transactionBytes));\n\n // Deserialize the authenticator bytes\n const authBytes = Uint8Array.from(parsed.senderAuthenticator);\n const senderAuthenticator = AccountAuthenticator.deserialize(new Deserializer(authBytes));\n\n // Only Entry Function transactions are supported\n if (!isEntryFunctionPayload(transaction.rawTransaction.payload)) {\n return { transaction, senderAuthenticator };\n }\n\n const entryFunction = transaction.rawTransaction.payload.entryFunction;\n\n return { transaction, senderAuthenticator, entryFunction };\n}\n\n/**\n * Checks if it's an entry function payload.\n *\n * @param payload - The payload to check\n * @returns True if it's an entry function payload\n */\nexport function isEntryFunctionPayload(\n payload: TransactionPayload,\n): payload is TransactionPayloadEntryFunction {\n return \"entryFunction\" in payload;\n}\n\n/**\n * Create an Aptos SDK client for the given network\n *\n * @param network - CAIP-2 network identifier (e.g., \"aptos:1\")\n * @param rpcUrl - Optional custom RPC URL\n * @returns Aptos SDK client\n */\nexport function createAptosClient(network: string, rpcUrl?: string): Aptos {\n const aptosNetwork = getAptosNetwork(network);\n const fullnodeUrl = rpcUrl || getAptosRpcUrl(aptosNetwork);\n\n const config = new AptosConfig({\n network: aptosNetwork,\n fullnode: fullnodeUrl,\n });\n\n return new Aptos(config);\n}\n\n/**\n * Encode an Aptos payment payload to base64\n *\n * @param transactionBytes - The serialized transaction bytes\n * @param authenticatorBytes - The serialized authenticator bytes\n * @returns Base64 encoded payload\n */\nexport function encodeAptosPayload(\n transactionBytes: Uint8Array,\n authenticatorBytes: Uint8Array,\n): string {\n const payload: DecodedAptosPayload = {\n transaction: Array.from(transactionBytes),\n senderAuthenticator: Array.from(authenticatorBytes),\n };\n return Buffer.from(JSON.stringify(payload)).toString(\"base64\");\n}\n"],"mappings":";;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,OACK;AAUA,SAAS,wBAAwB,mBAItC;AAEA,QAAM,UAAU,OAAO,KAAK,mBAAmB,QAAQ,EAAE,SAAS,MAAM;AACxE,QAAM,SAA8B,KAAK,MAAM,OAAO;AAGtD,QAAM,mBAAmB,WAAW,KAAK,OAAO,WAAW;AAC3D,QAAM,cAAc,kBAAkB,YAAY,IAAI,aAAa,gBAAgB,CAAC;AAGpF,QAAM,YAAY,WAAW,KAAK,OAAO,mBAAmB;AAC5D,QAAM,sBAAsB,qBAAqB,YAAY,IAAI,aAAa,SAAS,CAAC;AAGxF,MAAI,CAAC,uBAAuB,YAAY,eAAe,OAAO,GAAG;AAC/D,WAAO,EAAE,aAAa,oBAAoB;AAAA,EAC5C;AAEA,QAAM,gBAAgB,YAAY,eAAe,QAAQ;AAEzD,SAAO,EAAE,aAAa,qBAAqB,cAAc;AAC3D;AAQO,SAAS,uBACd,SAC4C;AAC5C,SAAO,mBAAmB;AAC5B;AASO,SAAS,kBAAkB,SAAiB,QAAwB;AACzE,QAAM,eAAe,gBAAgB,OAAO;AAC5C,QAAM,cAAc,UAAU,eAAe,YAAY;AAEzD,QAAM,SAAS,IAAI,YAAY;AAAA,IAC7B,SAAS;AAAA,IACT,UAAU;AAAA,EACZ,CAAC;AAED,SAAO,IAAI,MAAM,MAAM;AACzB;AASO,SAAS,mBACd,kBACA,oBACQ;AACR,QAAM,UAA+B;AAAA,IACnC,aAAa,MAAM,KAAK,gBAAgB;AAAA,IACxC,qBAAqB,MAAM,KAAK,kBAAkB;AAAA,EACpD;AACA,SAAO,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,EAAE,SAAS,QAAQ;AAC/D;","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
import { Network, NetworkToNodeAPI } from "@aptos-labs/ts-sdk";
|
|
3
|
+
var APTOS_MAINNET_CAIP2 = "aptos:1";
|
|
4
|
+
var APTOS_TESTNET_CAIP2 = "aptos:2";
|
|
5
|
+
var APTOS_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;
|
|
6
|
+
var TRANSFER_FUNCTION = "0x1::primary_fungible_store::transfer";
|
|
7
|
+
var MAX_GAS_AMOUNT = 500000n;
|
|
8
|
+
function getAptosChainId(network) {
|
|
9
|
+
switch (network) {
|
|
10
|
+
case APTOS_MAINNET_CAIP2:
|
|
11
|
+
return 1;
|
|
12
|
+
case APTOS_TESTNET_CAIP2:
|
|
13
|
+
return 2;
|
|
14
|
+
default:
|
|
15
|
+
throw new Error(`Unsupported Aptos network: ${network}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
var USDC_MAINNET_FA = "0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b";
|
|
19
|
+
var USDC_TESTNET_FA = "0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832";
|
|
20
|
+
function getAptosNetwork(network) {
|
|
21
|
+
switch (network) {
|
|
22
|
+
case APTOS_MAINNET_CAIP2:
|
|
23
|
+
return Network.MAINNET;
|
|
24
|
+
case APTOS_TESTNET_CAIP2:
|
|
25
|
+
return Network.TESTNET;
|
|
26
|
+
default:
|
|
27
|
+
throw new Error(`Unsupported Aptos network: ${network}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function getAptosRpcUrl(network) {
|
|
31
|
+
return NetworkToNodeAPI[network];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export {
|
|
35
|
+
APTOS_MAINNET_CAIP2,
|
|
36
|
+
APTOS_TESTNET_CAIP2,
|
|
37
|
+
APTOS_ADDRESS_REGEX,
|
|
38
|
+
TRANSFER_FUNCTION,
|
|
39
|
+
MAX_GAS_AMOUNT,
|
|
40
|
+
getAptosChainId,
|
|
41
|
+
USDC_MAINNET_FA,
|
|
42
|
+
USDC_TESTNET_FA,
|
|
43
|
+
getAptosNetwork,
|
|
44
|
+
getAptosRpcUrl
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-FG4ANPDN.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/constants.ts"],"sourcesContent":["import { Network, NetworkToNodeAPI } from \"@aptos-labs/ts-sdk\";\n\n/**\n * CAIP-2 network identifier for Aptos Mainnet\n */\nexport const APTOS_MAINNET_CAIP2 = \"aptos:1\";\n\n/**\n * CAIP-2 network identifier for Aptos Testnet\n */\nexport const APTOS_TESTNET_CAIP2 = \"aptos:2\";\n\n/**\n * Regex pattern for validating Aptos addresses\n * Matches 64 hex characters with 0x prefix\n */\nexport const APTOS_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;\n\n/**\n * The primary fungible store transfer function\n */\nexport const TRANSFER_FUNCTION = \"0x1::primary_fungible_store::transfer\";\n\n/**\n * Maximum gas amount allowed for sponsored transactions to prevent gas draining attacks.\n * The Aptos SDK defaults to 200000 for simple transactions, so we allow some headroom.\n */\nexport const MAX_GAS_AMOUNT = 500000n;\n\n/**\n * Maps CAIP-2 network identifiers to Aptos chain IDs.\n *\n * @param network - The CAIP-2 network identifier (e.g., \"aptos:1\")\n * @returns The corresponding chain ID\n */\nexport function getAptosChainId(network: string): number {\n switch (network) {\n case APTOS_MAINNET_CAIP2:\n return 1;\n case APTOS_TESTNET_CAIP2:\n return 2;\n default:\n throw new Error(`Unsupported Aptos network: ${network}`);\n }\n}\n\n/**\n * Default USDC fungible asset metadata address on mainnet.\n */\nexport const USDC_MAINNET_FA = \"0xbae207659db88bea0cbead6da0ed00aac12edcdda169e591cd41c94180b46f3b\";\n\n/**\n * Default USDC fungible asset metadata address on testnet.\n */\nexport const USDC_TESTNET_FA = \"0x69091fbab5f7d635ee7ac5098cf0c1efbe31d68fec0f2cd565e8d168daf52832\";\n\n/**\n * Maps CAIP-2 network identifiers to Aptos SDK Network enum.\n *\n * @param network - The CAIP-2 network identifier (e.g., \"aptos:1\")\n * @returns The corresponding Aptos SDK Network enum value\n */\nexport function getAptosNetwork(network: string): Network {\n switch (network) {\n case APTOS_MAINNET_CAIP2:\n return Network.MAINNET;\n case APTOS_TESTNET_CAIP2:\n return Network.TESTNET;\n default:\n throw new Error(`Unsupported Aptos network: ${network}`);\n }\n}\n\n/**\n * Gets the default RPC URL for the given Aptos network.\n *\n * @param network - The Aptos SDK Network enum value\n * @returns The default RPC URL for the network\n */\nexport function getAptosRpcUrl(network: Network): string {\n return NetworkToNodeAPI[network];\n}\n"],"mappings":";AAAA,SAAS,SAAS,wBAAwB;AAKnC,IAAM,sBAAsB;AAK5B,IAAM,sBAAsB;AAM5B,IAAM,sBAAsB;AAK5B,IAAM,oBAAoB;AAM1B,IAAM,iBAAiB;AAQvB,SAAS,gBAAgB,SAAyB;AACvD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,YAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,EAC3D;AACF;AAKO,IAAM,kBAAkB;AAKxB,IAAM,kBAAkB;AAQxB,SAAS,gBAAgB,SAA0B;AACxD,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,QAAQ;AAAA,IACjB,KAAK;AACH,aAAO,QAAQ;AAAA,IACjB;AACE,YAAM,IAAI,MAAM,8BAA8B,OAAO,EAAE;AAAA,EAC3D;AACF;AAQO,SAAS,eAAe,SAA0B;AACvD,SAAO,iBAAiB,OAAO;AACjC;","names":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SchemeNetworkClient, PaymentRequirements, PaymentPayload } from '@x402/core/types';
|
|
2
|
+
import { a as ClientAptosSigner, C as ClientAptosConfig } from '../../signer-DPT9P1NX.mjs';
|
|
3
|
+
import '@aptos-labs/ts-sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Aptos client implementation for the Exact payment scheme.
|
|
7
|
+
*/
|
|
8
|
+
declare class ExactAptosScheme implements SchemeNetworkClient {
|
|
9
|
+
private readonly signer;
|
|
10
|
+
private readonly config?;
|
|
11
|
+
readonly scheme = "exact";
|
|
12
|
+
/**
|
|
13
|
+
* Creates a new ExactAptosScheme instance.
|
|
14
|
+
*
|
|
15
|
+
* @param signer - The Aptos account for signing transactions
|
|
16
|
+
* @param config - Optional configuration with custom RPC URL
|
|
17
|
+
*/
|
|
18
|
+
constructor(signer: ClientAptosSigner, config?: ClientAptosConfig | undefined);
|
|
19
|
+
/**
|
|
20
|
+
* Creates a payment payload for the Exact scheme.
|
|
21
|
+
*
|
|
22
|
+
* @param x402Version - The x402 protocol version
|
|
23
|
+
* @param paymentRequirements - The payment requirements
|
|
24
|
+
* @returns Promise resolving to a payment payload
|
|
25
|
+
*/
|
|
26
|
+
createPaymentPayload(x402Version: number, paymentRequirements: PaymentRequirements): Promise<Pick<PaymentPayload, "x402Version" | "payload">>;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { ExactAptosScheme };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { SchemeNetworkFacilitator, PaymentPayload, PaymentRequirements, VerifyResponse, SettleResponse } from '@x402/core/types';
|
|
2
|
+
import { F as FacilitatorAptosSigner } from '../../signer-DPT9P1NX.mjs';
|
|
3
|
+
import '@aptos-labs/ts-sdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Aptos facilitator implementation for the Exact payment scheme.
|
|
7
|
+
*/
|
|
8
|
+
declare class ExactAptosScheme implements SchemeNetworkFacilitator {
|
|
9
|
+
private readonly signer;
|
|
10
|
+
private readonly sponsorTransactions;
|
|
11
|
+
readonly scheme = "exact";
|
|
12
|
+
readonly caipFamily = "aptos:*";
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new ExactAptosFacilitator instance.
|
|
15
|
+
*
|
|
16
|
+
* @param signer - The Aptos facilitator signer for transaction submission
|
|
17
|
+
* @param sponsorTransactions - Whether to sponsor transactions (pay gas fees). Defaults to true.
|
|
18
|
+
*/
|
|
19
|
+
constructor(signer: FacilitatorAptosSigner, sponsorTransactions?: boolean);
|
|
20
|
+
/**
|
|
21
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
22
|
+
*
|
|
23
|
+
* @param _ - The network identifier (unused)
|
|
24
|
+
* @returns Extra data with fee payer address, or undefined if sponsorship is disabled
|
|
25
|
+
*/
|
|
26
|
+
getExtra(_: string): Record<string, unknown> | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Get signer addresses used by this facilitator.
|
|
29
|
+
*
|
|
30
|
+
* @param _ - The network identifier (unused)
|
|
31
|
+
* @returns Array of fee payer addresses
|
|
32
|
+
*/
|
|
33
|
+
getSigners(_: string): string[];
|
|
34
|
+
/**
|
|
35
|
+
* Verifies a payment payload.
|
|
36
|
+
*
|
|
37
|
+
* @param payload - The payment payload to verify
|
|
38
|
+
* @param requirements - The payment requirements
|
|
39
|
+
* @returns Promise resolving to verification response
|
|
40
|
+
*/
|
|
41
|
+
verify(payload: PaymentPayload, requirements: PaymentRequirements): Promise<VerifyResponse>;
|
|
42
|
+
/**
|
|
43
|
+
* Settles a payment by submitting the transaction.
|
|
44
|
+
*
|
|
45
|
+
* @param payload - The payment payload to settle
|
|
46
|
+
* @param requirements - The payment requirements
|
|
47
|
+
* @returns Promise resolving to settlement response
|
|
48
|
+
*/
|
|
49
|
+
settle(payload: PaymentPayload, requirements: PaymentRequirements): Promise<SettleResponse>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { ExactAptosScheme };
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createAptosClient,
|
|
3
|
+
deserializeAptosPayment
|
|
4
|
+
} from "../../chunk-D4UVBSUH.mjs";
|
|
5
|
+
import {
|
|
6
|
+
MAX_GAS_AMOUNT,
|
|
7
|
+
getAptosChainId
|
|
8
|
+
} from "../../chunk-FG4ANPDN.mjs";
|
|
9
|
+
|
|
10
|
+
// src/exact/facilitator/scheme.ts
|
|
11
|
+
import { AccountAddress, Deserializer } from "@aptos-labs/ts-sdk";
|
|
12
|
+
var ExactAptosScheme = class {
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new ExactAptosFacilitator instance.
|
|
15
|
+
*
|
|
16
|
+
* @param signer - The Aptos facilitator signer for transaction submission
|
|
17
|
+
* @param sponsorTransactions - Whether to sponsor transactions (pay gas fees). Defaults to true.
|
|
18
|
+
*/
|
|
19
|
+
constructor(signer, sponsorTransactions = true) {
|
|
20
|
+
this.signer = signer;
|
|
21
|
+
this.sponsorTransactions = sponsorTransactions;
|
|
22
|
+
this.scheme = "exact";
|
|
23
|
+
this.caipFamily = "aptos:*";
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Get mechanism-specific extra data for the supported kinds endpoint.
|
|
27
|
+
*
|
|
28
|
+
* @param _ - The network identifier (unused)
|
|
29
|
+
* @returns Extra data with fee payer address, or undefined if sponsorship is disabled
|
|
30
|
+
*/
|
|
31
|
+
getExtra(_) {
|
|
32
|
+
if (!this.sponsorTransactions) {
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
const addresses = this.signer.getAddresses();
|
|
36
|
+
const randomIndex = Math.floor(Math.random() * addresses.length);
|
|
37
|
+
return { feePayer: addresses[randomIndex] };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get signer addresses used by this facilitator.
|
|
41
|
+
*
|
|
42
|
+
* @param _ - The network identifier (unused)
|
|
43
|
+
* @returns Array of fee payer addresses
|
|
44
|
+
*/
|
|
45
|
+
getSigners(_) {
|
|
46
|
+
return [...this.signer.getAddresses()];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Verifies a payment payload.
|
|
50
|
+
*
|
|
51
|
+
* @param payload - The payment payload to verify
|
|
52
|
+
* @param requirements - The payment requirements
|
|
53
|
+
* @returns Promise resolving to verification response
|
|
54
|
+
*/
|
|
55
|
+
async verify(payload, requirements) {
|
|
56
|
+
try {
|
|
57
|
+
const aptosPayload = payload.payload;
|
|
58
|
+
const signerAddresses = this.signer.getAddresses();
|
|
59
|
+
const isSponsored = typeof requirements.extra?.feePayer === "string";
|
|
60
|
+
if (payload.x402Version !== 2) {
|
|
61
|
+
return {
|
|
62
|
+
isValid: false,
|
|
63
|
+
invalidReason: "invalid_exact_aptos_payload_unsupported_version",
|
|
64
|
+
payer: ""
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
if (payload.accepted.scheme !== "exact" || requirements.scheme !== "exact") {
|
|
68
|
+
return { isValid: false, invalidReason: "unsupported_scheme", payer: "" };
|
|
69
|
+
}
|
|
70
|
+
if (payload.accepted.network !== requirements.network) {
|
|
71
|
+
return { isValid: false, invalidReason: "network_mismatch", payer: "" };
|
|
72
|
+
}
|
|
73
|
+
if (isSponsored && !signerAddresses.includes(requirements.extra.feePayer)) {
|
|
74
|
+
return { isValid: false, invalidReason: "fee_payer_not_managed_by_facilitator", payer: "" };
|
|
75
|
+
}
|
|
76
|
+
const { transaction, senderAuthenticator, entryFunction } = deserializeAptosPayment(
|
|
77
|
+
aptosPayload.transaction
|
|
78
|
+
);
|
|
79
|
+
const senderAddress = transaction.rawTransaction.sender.toString();
|
|
80
|
+
const expectedChainId = getAptosChainId(requirements.network);
|
|
81
|
+
const txChainId = Number(transaction.rawTransaction.chain_id.chainId);
|
|
82
|
+
if (txChainId !== expectedChainId) {
|
|
83
|
+
return {
|
|
84
|
+
isValid: false,
|
|
85
|
+
invalidReason: `invalid_exact_aptos_payload_chain_id_mismatch: expected ${expectedChainId}, got ${txChainId}`,
|
|
86
|
+
payer: senderAddress
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (senderAuthenticator.isEd25519()) {
|
|
90
|
+
const pubKey = senderAuthenticator.public_key;
|
|
91
|
+
const derivedAddress = AccountAddress.from(pubKey.authKey().derivedAddress());
|
|
92
|
+
if (!derivedAddress.equals(transaction.rawTransaction.sender)) {
|
|
93
|
+
return {
|
|
94
|
+
isValid: false,
|
|
95
|
+
invalidReason: "invalid_exact_aptos_payload_sender_authenticator_mismatch",
|
|
96
|
+
payer: senderAddress
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (isSponsored) {
|
|
101
|
+
const maxGasAmount = BigInt(transaction.rawTransaction.max_gas_amount);
|
|
102
|
+
if (maxGasAmount > MAX_GAS_AMOUNT) {
|
|
103
|
+
return {
|
|
104
|
+
isValid: false,
|
|
105
|
+
invalidReason: `invalid_exact_aptos_payload_gas_too_high: ${maxGasAmount} > ${MAX_GAS_AMOUNT}`,
|
|
106
|
+
payer: senderAddress
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (isSponsored) {
|
|
111
|
+
const expectedFeePayer = AccountAddress.from(requirements.extra.feePayer);
|
|
112
|
+
if (!transaction.feePayerAddress || !expectedFeePayer.equals(transaction.feePayerAddress)) {
|
|
113
|
+
return {
|
|
114
|
+
isValid: false,
|
|
115
|
+
invalidReason: "invalid_exact_aptos_payload_fee_payer_mismatch",
|
|
116
|
+
payer: senderAddress
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (isSponsored && signerAddresses.includes(senderAddress)) {
|
|
121
|
+
return {
|
|
122
|
+
isValid: false,
|
|
123
|
+
invalidReason: "invalid_exact_aptos_payload_fee_payer_transferring_funds",
|
|
124
|
+
payer: senderAddress
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const EXPIRATION_BUFFER_SECONDS = 5;
|
|
128
|
+
const expirationTimestamp = Number(transaction.rawTransaction.expiration_timestamp_secs);
|
|
129
|
+
if (expirationTimestamp < Math.floor(Date.now() / 1e3) + EXPIRATION_BUFFER_SECONDS) {
|
|
130
|
+
return {
|
|
131
|
+
isValid: false,
|
|
132
|
+
invalidReason: "invalid_exact_aptos_payload_transaction_expired",
|
|
133
|
+
payer: senderAddress
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
if (!entryFunction) {
|
|
137
|
+
return {
|
|
138
|
+
isValid: false,
|
|
139
|
+
invalidReason: "invalid_exact_aptos_payload_missing_entry_function",
|
|
140
|
+
payer: senderAddress
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const moduleAddress = entryFunction.module_name.address;
|
|
144
|
+
const moduleName = entryFunction.module_name.name.identifier;
|
|
145
|
+
const functionName = entryFunction.function_name.identifier;
|
|
146
|
+
const isPrimaryFungibleStore = AccountAddress.ONE.equals(moduleAddress) && moduleName === "primary_fungible_store" && functionName === "transfer";
|
|
147
|
+
const isFungibleAsset = AccountAddress.ONE.equals(moduleAddress) && moduleName === "fungible_asset" && functionName === "transfer";
|
|
148
|
+
if (!isPrimaryFungibleStore && !isFungibleAsset) {
|
|
149
|
+
return {
|
|
150
|
+
isValid: false,
|
|
151
|
+
invalidReason: "invalid_exact_aptos_payload_wrong_function",
|
|
152
|
+
payer: senderAddress
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (entryFunction.type_args.length !== 1) {
|
|
156
|
+
return {
|
|
157
|
+
isValid: false,
|
|
158
|
+
invalidReason: "invalid_exact_aptos_payload_wrong_type_args",
|
|
159
|
+
payer: senderAddress
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
const args = entryFunction.args;
|
|
163
|
+
if (args.length !== 3) {
|
|
164
|
+
return {
|
|
165
|
+
isValid: false,
|
|
166
|
+
invalidReason: "invalid_exact_aptos_payload_wrong_args",
|
|
167
|
+
payer: senderAddress
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
const [faAddressArg, recipientAddressArg, amountArg] = args;
|
|
171
|
+
const faAddress = AccountAddress.from(faAddressArg.bcsToBytes());
|
|
172
|
+
if (!faAddress.equals(AccountAddress.from(requirements.asset))) {
|
|
173
|
+
return {
|
|
174
|
+
isValid: false,
|
|
175
|
+
invalidReason: "invalid_exact_aptos_payload_asset_mismatch",
|
|
176
|
+
payer: senderAddress
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
const amount = new Deserializer(amountArg.bcsToBytes()).deserializeU64().toString(10);
|
|
180
|
+
if (amount !== requirements.amount) {
|
|
181
|
+
return {
|
|
182
|
+
isValid: false,
|
|
183
|
+
invalidReason: "invalid_exact_aptos_payload_amount_mismatch",
|
|
184
|
+
payer: senderAddress
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const recipientAddress = AccountAddress.from(recipientAddressArg.bcsToBytes());
|
|
188
|
+
if (!recipientAddress.equals(AccountAddress.from(requirements.payTo))) {
|
|
189
|
+
return {
|
|
190
|
+
isValid: false,
|
|
191
|
+
invalidReason: "invalid_exact_aptos_payload_recipient_mismatch",
|
|
192
|
+
payer: senderAddress
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
const aptos = createAptosClient(requirements.network);
|
|
196
|
+
const balance = await aptos.getCurrentFungibleAssetBalances({
|
|
197
|
+
options: {
|
|
198
|
+
where: {
|
|
199
|
+
owner_address: { _eq: senderAddress },
|
|
200
|
+
asset_type: { _eq: requirements.asset }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
const currentBalance = BigInt(balance[0]?.amount ?? 0);
|
|
205
|
+
if (currentBalance < BigInt(requirements.amount)) {
|
|
206
|
+
return {
|
|
207
|
+
isValid: false,
|
|
208
|
+
invalidReason: "invalid_exact_aptos_payload_insufficient_balance",
|
|
209
|
+
payer: senderAddress
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
let publicKey;
|
|
213
|
+
if (senderAuthenticator.isEd25519()) {
|
|
214
|
+
publicKey = senderAuthenticator.public_key;
|
|
215
|
+
} else if (senderAuthenticator.isSingleKey()) {
|
|
216
|
+
publicKey = senderAuthenticator.public_key;
|
|
217
|
+
} else if (senderAuthenticator.isMultiKey()) {
|
|
218
|
+
publicKey = senderAuthenticator.public_keys;
|
|
219
|
+
}
|
|
220
|
+
const simulationResult = (await aptos.transaction.simulate.simple({ signerPublicKey: publicKey, transaction }))[0];
|
|
221
|
+
if (!simulationResult.success) {
|
|
222
|
+
return {
|
|
223
|
+
isValid: false,
|
|
224
|
+
invalidReason: `invalid_exact_aptos_payload_simulation_failed: ${simulationResult.vm_status}`,
|
|
225
|
+
payer: senderAddress
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
return { isValid: true, invalidReason: void 0, payer: senderAddress };
|
|
229
|
+
} catch (error) {
|
|
230
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
231
|
+
return {
|
|
232
|
+
isValid: false,
|
|
233
|
+
invalidReason: `invalid_exact_aptos_payload_verification_error: ${errorMessage}`,
|
|
234
|
+
payer: ""
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Settles a payment by submitting the transaction.
|
|
240
|
+
*
|
|
241
|
+
* @param payload - The payment payload to settle
|
|
242
|
+
* @param requirements - The payment requirements
|
|
243
|
+
* @returns Promise resolving to settlement response
|
|
244
|
+
*/
|
|
245
|
+
async settle(payload, requirements) {
|
|
246
|
+
const aptosPayload = payload.payload;
|
|
247
|
+
const valid = await this.verify(payload, requirements);
|
|
248
|
+
if (!valid.isValid) {
|
|
249
|
+
return {
|
|
250
|
+
success: false,
|
|
251
|
+
network: payload.accepted.network,
|
|
252
|
+
transaction: "",
|
|
253
|
+
errorReason: valid.invalidReason ?? "verification_failed",
|
|
254
|
+
payer: valid.payer || ""
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
try {
|
|
258
|
+
const { transaction, senderAuthenticator } = deserializeAptosPayment(
|
|
259
|
+
aptosPayload.transaction
|
|
260
|
+
);
|
|
261
|
+
const senderAddress = transaction.rawTransaction.sender.toStringLong();
|
|
262
|
+
const isSponsored = typeof requirements.extra?.feePayer === "string";
|
|
263
|
+
const pendingTxn = isSponsored ? await this.signer.signAndSubmitAsFeePayer(
|
|
264
|
+
transaction,
|
|
265
|
+
senderAuthenticator,
|
|
266
|
+
requirements.network
|
|
267
|
+
) : await this.signer.submitTransaction(
|
|
268
|
+
transaction,
|
|
269
|
+
senderAuthenticator,
|
|
270
|
+
requirements.network
|
|
271
|
+
);
|
|
272
|
+
await this.signer.waitForTransaction(pendingTxn.hash, requirements.network);
|
|
273
|
+
return {
|
|
274
|
+
success: true,
|
|
275
|
+
transaction: pendingTxn.hash,
|
|
276
|
+
network: payload.accepted.network,
|
|
277
|
+
payer: senderAddress
|
|
278
|
+
};
|
|
279
|
+
} catch (error) {
|
|
280
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
281
|
+
return {
|
|
282
|
+
success: false,
|
|
283
|
+
errorReason: `transaction_failed: ${errorMessage}`,
|
|
284
|
+
transaction: "",
|
|
285
|
+
network: payload.accepted.network,
|
|
286
|
+
payer: valid.payer || ""
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
};
|
|
291
|
+
export {
|
|
292
|
+
ExactAptosScheme
|
|
293
|
+
};
|
|
294
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/exact/facilitator/scheme.ts"],"sourcesContent":["import { AccountAddress, Deserializer, Ed25519PublicKey, PublicKey } from \"@aptos-labs/ts-sdk\";\nimport type {\n PaymentPayload,\n PaymentRequirements,\n SchemeNetworkFacilitator,\n SettleResponse,\n VerifyResponse,\n} from \"@x402/core/types\";\nimport type { FacilitatorAptosSigner } from \"../../signer\";\nimport type { ExactAptosPayload } from \"../../types\";\nimport { createAptosClient, deserializeAptosPayment } from \"../../utils\";\nimport { getAptosChainId, MAX_GAS_AMOUNT } from \"../../constants\";\n\n/**\n * Aptos facilitator implementation for the Exact payment scheme.\n */\nexport class ExactAptosScheme implements SchemeNetworkFacilitator {\n readonly scheme = \"exact\";\n readonly caipFamily = \"aptos:*\";\n\n /**\n * Creates a new ExactAptosFacilitator instance.\n *\n * @param signer - The Aptos facilitator signer for transaction submission\n * @param sponsorTransactions - Whether to sponsor transactions (pay gas fees). Defaults to true.\n */\n constructor(\n private readonly signer: FacilitatorAptosSigner,\n private readonly sponsorTransactions: boolean = true,\n ) {}\n\n /**\n * Get mechanism-specific extra data for the supported kinds endpoint.\n *\n * @param _ - The network identifier (unused)\n * @returns Extra data with fee payer address, or undefined if sponsorship is disabled\n */\n getExtra(_: string): Record<string, unknown> | undefined {\n if (!this.sponsorTransactions) {\n return undefined;\n }\n const addresses = this.signer.getAddresses();\n const randomIndex = Math.floor(Math.random() * addresses.length);\n return { feePayer: addresses[randomIndex] };\n }\n\n /**\n * Get signer addresses used by this facilitator.\n *\n * @param _ - The network identifier (unused)\n * @returns Array of fee payer addresses\n */\n getSigners(_: string): string[] {\n return [...this.signer.getAddresses()];\n }\n\n /**\n * Verifies a payment payload.\n *\n * @param payload - The payment payload to verify\n * @param requirements - The payment requirements\n * @returns Promise resolving to verification response\n */\n async verify(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<VerifyResponse> {\n try {\n const aptosPayload = payload.payload as ExactAptosPayload;\n const signerAddresses = this.signer.getAddresses();\n const isSponsored = typeof requirements.extra?.feePayer === \"string\";\n\n // Step 2: Verify x402Version is 2\n if (payload.x402Version !== 2) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_unsupported_version\",\n payer: \"\",\n };\n }\n\n // Step 3: Verify the network matches\n if (payload.accepted.scheme !== \"exact\" || requirements.scheme !== \"exact\") {\n return { isValid: false, invalidReason: \"unsupported_scheme\", payer: \"\" };\n }\n\n if (payload.accepted.network !== requirements.network) {\n return { isValid: false, invalidReason: \"network_mismatch\", payer: \"\" };\n }\n\n // If sponsored, verify the fee payer is managed by this facilitator\n if (isSponsored && !signerAddresses.includes(requirements.extra.feePayer as string)) {\n return { isValid: false, invalidReason: \"fee_payer_not_managed_by_facilitator\", payer: \"\" };\n }\n\n // Step 4: Deserialize the BCS-encoded transaction and verify the signature\n const { transaction, senderAuthenticator, entryFunction } = deserializeAptosPayment(\n aptosPayload.transaction,\n );\n const senderAddress = transaction.rawTransaction.sender.toString();\n\n // Verify chain ID matches expected network\n const expectedChainId = getAptosChainId(requirements.network);\n const txChainId = Number(transaction.rawTransaction.chain_id.chainId);\n if (txChainId !== expectedChainId) {\n return {\n isValid: false,\n invalidReason: `invalid_exact_aptos_payload_chain_id_mismatch: expected ${expectedChainId}, got ${txChainId}`,\n payer: senderAddress,\n };\n }\n\n // Verify sender matches authenticator public key (for Ed25519 accounts)\n // Note: SingleKey and MultiKey authenticators are validated during simulation (step 11)\n if (senderAuthenticator.isEd25519()) {\n const pubKey = senderAuthenticator.public_key as Ed25519PublicKey;\n const derivedAddress = AccountAddress.from(pubKey.authKey().derivedAddress());\n if (!derivedAddress.equals(transaction.rawTransaction.sender)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_sender_authenticator_mismatch\",\n payer: senderAddress,\n };\n }\n }\n\n // For sponsored transactions, verify max gas to prevent gas draining\n if (isSponsored) {\n const maxGasAmount = BigInt(transaction.rawTransaction.max_gas_amount);\n if (maxGasAmount > MAX_GAS_AMOUNT) {\n return {\n isValid: false,\n invalidReason: `invalid_exact_aptos_payload_gas_too_high: ${maxGasAmount} > ${MAX_GAS_AMOUNT}`,\n payer: senderAddress,\n };\n }\n }\n\n // For sponsored transactions, verify fee payer address matches\n if (isSponsored) {\n const expectedFeePayer = AccountAddress.from(requirements.extra.feePayer as string);\n if (!transaction.feePayerAddress || !expectedFeePayer.equals(transaction.feePayerAddress)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_fee_payer_mismatch\",\n payer: senderAddress,\n };\n }\n }\n\n // SECURITY (reference implementation): Prevent facilitator from signing away their own tokens\n if (isSponsored && signerAddresses.includes(senderAddress)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_fee_payer_transferring_funds\",\n payer: senderAddress,\n };\n }\n\n // Step 5: Verify the transaction has not expired\n const EXPIRATION_BUFFER_SECONDS = 5;\n const expirationTimestamp = Number(transaction.rawTransaction.expiration_timestamp_secs);\n if (expirationTimestamp < Math.floor(Date.now() / 1000) + EXPIRATION_BUFFER_SECONDS) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_transaction_expired\",\n payer: senderAddress,\n };\n }\n\n // Step 6: Verify the transaction contains a fungible asset transfer operation\n // We accept both primary_fungible_store::transfer and fungible_asset::transfer:\n // - primary_fungible_store::transfer operates on primary stores (the default store for each asset)\n // and automatically creates the recipient's store if it doesn't exist\n // - fungible_asset::transfer is a lower-level function for arbitrary store-to-store transfers\n // and is more gas efficient when stores already exist\n if (!entryFunction) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_missing_entry_function\",\n payer: senderAddress,\n };\n }\n\n const moduleAddress = entryFunction.module_name.address;\n const moduleName = entryFunction.module_name.name.identifier;\n const functionName = entryFunction.function_name.identifier;\n\n const isPrimaryFungibleStore =\n AccountAddress.ONE.equals(moduleAddress) &&\n moduleName === \"primary_fungible_store\" &&\n functionName === \"transfer\";\n\n const isFungibleAsset =\n AccountAddress.ONE.equals(moduleAddress) &&\n moduleName === \"fungible_asset\" &&\n functionName === \"transfer\";\n\n if (!isPrimaryFungibleStore && !isFungibleAsset) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_wrong_function\",\n payer: senderAddress,\n };\n }\n\n if (entryFunction.type_args.length !== 1) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_wrong_type_args\",\n payer: senderAddress,\n };\n }\n\n const args = entryFunction.args;\n if (args.length !== 3) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_wrong_args\",\n payer: senderAddress,\n };\n }\n\n const [faAddressArg, recipientAddressArg, amountArg] = args;\n\n // Step 7: Verify the transfer is for the correct asset\n const faAddress = AccountAddress.from(faAddressArg.bcsToBytes());\n if (!faAddress.equals(AccountAddress.from(requirements.asset))) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_asset_mismatch\",\n payer: senderAddress,\n };\n }\n\n // Step 8: Verify the transfer amount matches\n const amount = new Deserializer(amountArg.bcsToBytes()).deserializeU64().toString(10);\n if (amount !== requirements.amount) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_amount_mismatch\",\n payer: senderAddress,\n };\n }\n\n // Step 9: Verify the transfer recipient matches\n const recipientAddress = AccountAddress.from(recipientAddressArg.bcsToBytes());\n if (!recipientAddress.equals(AccountAddress.from(requirements.payTo))) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_recipient_mismatch\",\n payer: senderAddress,\n };\n }\n\n // Step 10: Verify the sender has sufficient balance\n const aptos = createAptosClient(requirements.network);\n const balance = await aptos.getCurrentFungibleAssetBalances({\n options: {\n where: {\n owner_address: { _eq: senderAddress },\n asset_type: { _eq: requirements.asset },\n },\n },\n });\n const currentBalance = BigInt(balance[0]?.amount ?? 0);\n if (currentBalance < BigInt(requirements.amount)) {\n return {\n isValid: false,\n invalidReason: \"invalid_exact_aptos_payload_insufficient_balance\",\n payer: senderAddress,\n };\n }\n\n // Step 11: Simulate the transaction\n let publicKey: PublicKey | undefined;\n if (senderAuthenticator.isEd25519()) {\n publicKey = senderAuthenticator.public_key;\n } else if (senderAuthenticator.isSingleKey()) {\n publicKey = senderAuthenticator.public_key;\n } else if (senderAuthenticator.isMultiKey()) {\n publicKey = senderAuthenticator.public_keys;\n }\n\n const simulationResult = (\n await aptos.transaction.simulate.simple({ signerPublicKey: publicKey, transaction })\n )[0];\n\n if (!simulationResult.success) {\n return {\n isValid: false,\n invalidReason: `invalid_exact_aptos_payload_simulation_failed: ${simulationResult.vm_status}`,\n payer: senderAddress,\n };\n }\n\n return { isValid: true, invalidReason: undefined, payer: senderAddress };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n isValid: false,\n invalidReason: `invalid_exact_aptos_payload_verification_error: ${errorMessage}`,\n payer: \"\",\n };\n }\n }\n\n /**\n * Settles a payment by submitting the transaction.\n *\n * @param payload - The payment payload to settle\n * @param requirements - The payment requirements\n * @returns Promise resolving to settlement response\n */\n async settle(\n payload: PaymentPayload,\n requirements: PaymentRequirements,\n ): Promise<SettleResponse> {\n const aptosPayload = payload.payload as ExactAptosPayload;\n\n const valid = await this.verify(payload, requirements);\n if (!valid.isValid) {\n return {\n success: false,\n network: payload.accepted.network,\n transaction: \"\",\n errorReason: valid.invalidReason ?? \"verification_failed\",\n payer: valid.payer || \"\",\n };\n }\n\n try {\n const { transaction, senderAuthenticator } = deserializeAptosPayment(\n aptosPayload.transaction,\n );\n const senderAddress = transaction.rawTransaction.sender.toStringLong();\n const isSponsored = typeof requirements.extra?.feePayer === \"string\";\n\n const pendingTxn = isSponsored\n ? await this.signer.signAndSubmitAsFeePayer(\n transaction,\n senderAuthenticator,\n requirements.network,\n )\n : await this.signer.submitTransaction(\n transaction,\n senderAuthenticator,\n requirements.network,\n );\n\n await this.signer.waitForTransaction(pendingTxn.hash, requirements.network);\n\n return {\n success: true,\n transaction: pendingTxn.hash,\n network: payload.accepted.network,\n payer: senderAddress,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n errorReason: `transaction_failed: ${errorMessage}`,\n transaction: \"\",\n network: payload.accepted.network,\n payer: valid.payer || \"\",\n };\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SchemeNetworkServer, MoneyParser, Price, Network, AssetAmount, PaymentRequirements } from '@x402/core/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Aptos server implementation for the Exact payment scheme.
|
|
5
|
+
*/
|
|
6
|
+
declare class ExactAptosScheme implements SchemeNetworkServer {
|
|
7
|
+
readonly scheme = "exact";
|
|
8
|
+
private moneyParsers;
|
|
9
|
+
/**
|
|
10
|
+
* Register a custom money parser in the parser chain.
|
|
11
|
+
*
|
|
12
|
+
* @param parser - Custom function to convert amount to AssetAmount (or null to skip)
|
|
13
|
+
* @returns The service instance for chaining
|
|
14
|
+
*/
|
|
15
|
+
registerMoneyParser(parser: MoneyParser): ExactAptosScheme;
|
|
16
|
+
/**
|
|
17
|
+
* Parses a price into an asset amount.
|
|
18
|
+
*
|
|
19
|
+
* @param price - The price to parse
|
|
20
|
+
* @param network - The network to use
|
|
21
|
+
* @returns Promise that resolves to the parsed asset amount
|
|
22
|
+
*/
|
|
23
|
+
parsePrice(price: Price, network: Network): Promise<AssetAmount>;
|
|
24
|
+
/**
|
|
25
|
+
* Build payment requirements for this scheme/network combination
|
|
26
|
+
*
|
|
27
|
+
* @param paymentRequirements - The base payment requirements
|
|
28
|
+
* @param supportedKind - The supported kind configuration
|
|
29
|
+
* @param supportedKind.x402Version - The x402 protocol version
|
|
30
|
+
* @param supportedKind.scheme - The payment scheme
|
|
31
|
+
* @param supportedKind.network - The network identifier
|
|
32
|
+
* @param supportedKind.extra - Extra metadata including feePayer address
|
|
33
|
+
* @param extensionKeys - Extension keys supported by the facilitator
|
|
34
|
+
* @returns Enhanced payment requirements with feePayer in extra
|
|
35
|
+
*/
|
|
36
|
+
enhancePaymentRequirements(paymentRequirements: PaymentRequirements, supportedKind: {
|
|
37
|
+
x402Version: number;
|
|
38
|
+
scheme: string;
|
|
39
|
+
network: Network;
|
|
40
|
+
extra?: Record<string, unknown>;
|
|
41
|
+
}, extensionKeys: string[]): Promise<PaymentRequirements>;
|
|
42
|
+
/**
|
|
43
|
+
* Parse Money to a decimal number.
|
|
44
|
+
*
|
|
45
|
+
* @param money - The money value to parse
|
|
46
|
+
* @returns Decimal number
|
|
47
|
+
*/
|
|
48
|
+
private parseMoneyToDecimal;
|
|
49
|
+
/**
|
|
50
|
+
* Default money conversion to USDC.
|
|
51
|
+
*
|
|
52
|
+
* @param amount - The decimal amount
|
|
53
|
+
* @param network - The network to use
|
|
54
|
+
* @returns The parsed asset amount in USDC
|
|
55
|
+
*/
|
|
56
|
+
private defaultMoneyConversion;
|
|
57
|
+
/**
|
|
58
|
+
* Convert a decimal amount string to a token amount string.
|
|
59
|
+
*
|
|
60
|
+
* @param amount - The decimal amount
|
|
61
|
+
* @param decimals - Number of decimals for the token
|
|
62
|
+
* @returns The amount in atomic units as a string
|
|
63
|
+
*/
|
|
64
|
+
private convertToTokenAmount;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { ExactAptosScheme };
|