@4mica/sdk 1.0.1 → 1.1.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.
Files changed (62) hide show
  1. package/README.md +1 -1
  2. package/dist/client/recipient.d.ts +2 -1
  3. package/dist/client/recipient.js +3 -1
  4. package/dist/contract.js +26 -10
  5. package/dist/guarantee.d.ts +1 -1
  6. package/dist/guarantee.js +9 -4
  7. package/dist/models.d.ts +4 -0
  8. package/dist/models.js +3 -0
  9. package/dist/payment.d.ts +2 -1
  10. package/dist/payment.js +2 -1
  11. package/dist/signing.d.ts +4 -0
  12. package/dist/signing.js +4 -0
  13. package/dist/validation.d.ts +2 -2
  14. package/dist/validation.js +4 -2
  15. package/dist/x402/index.d.ts +1 -1
  16. package/dist/x402/index.js +4 -2
  17. package/dist/x402/models.d.ts +1 -0
  18. package/package.json +4 -2
  19. package/dist/abi/core4mica.json +0 -1605
  20. package/dist/abi/erc20.json +0 -187
  21. package/dist/client.d.ts +0 -56
  22. package/dist/client.js +0 -258
  23. package/dist/src/abi/core4mica.json +0 -1605
  24. package/dist/src/abi/erc20.json +0 -187
  25. package/dist/src/bls.d.ts +0 -5
  26. package/dist/src/bls.js +0 -45
  27. package/dist/src/client.d.ts +0 -55
  28. package/dist/src/client.js +0 -214
  29. package/dist/src/config.d.ts +0 -21
  30. package/dist/src/config.js +0 -76
  31. package/dist/src/contract.d.ts +0 -33
  32. package/dist/src/contract.js +0 -121
  33. package/dist/src/errors.d.ts +0 -17
  34. package/dist/src/errors.js +0 -31
  35. package/dist/src/guarantee.d.ts +0 -3
  36. package/dist/src/guarantee.js +0 -66
  37. package/dist/src/index.d.ts +0 -11
  38. package/dist/src/index.js +0 -27
  39. package/dist/src/models.d.ts +0 -119
  40. package/dist/src/models.js +0 -132
  41. package/dist/src/rpc.d.ts +0 -30
  42. package/dist/src/rpc.js +0 -122
  43. package/dist/src/signing.d.ts +0 -16
  44. package/dist/src/signing.js +0 -102
  45. package/dist/src/utils.d.ts +0 -8
  46. package/dist/src/utils.js +0 -78
  47. package/dist/src/x402.d.ts +0 -77
  48. package/dist/src/x402.js +0 -214
  49. package/dist/tests/config.test.d.ts +0 -1
  50. package/dist/tests/config.test.js +0 -26
  51. package/dist/tests/guarantee.test.d.ts +0 -1
  52. package/dist/tests/guarantee.test.js +0 -26
  53. package/dist/tests/rpc.test.d.ts +0 -1
  54. package/dist/tests/rpc.test.js +0 -44
  55. package/dist/tests/signing.test.d.ts +0 -1
  56. package/dist/tests/signing.test.js +0 -25
  57. package/dist/tests/utils.test.d.ts +0 -1
  58. package/dist/tests/utils.test.js +0 -25
  59. package/dist/tests/x402.test.d.ts +0 -1
  60. package/dist/tests/x402.test.js +0 -65
  61. package/dist/x402.d.ts +0 -78
  62. package/dist/x402.js +0 -231
package/dist/src/rpc.js DELETED
@@ -1,122 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RpcProxy = void 0;
4
- const signing_1 = require("./signing");
5
- const errors_1 = require("./errors");
6
- const ADMIN_API_KEY_HEADER = 'x-api-key';
7
- function serializeTabId(tabId) {
8
- return `0x${BigInt(tabId).toString(16)}`;
9
- }
10
- class RpcProxy {
11
- constructor(endpoint, adminApiKey, fetchFn = fetch) {
12
- this.baseUrl = endpoint.endsWith('/') ? endpoint.slice(0, -1) : endpoint;
13
- this.adminApiKey = adminApiKey;
14
- this.fetchFn = fetchFn;
15
- }
16
- async aclose() {
17
- // no-op for symmetry with Python SDK
18
- }
19
- headers() {
20
- const headers = {};
21
- if (this.adminApiKey) {
22
- headers[ADMIN_API_KEY_HEADER] = this.adminApiKey;
23
- }
24
- return headers;
25
- }
26
- async decode(response) {
27
- let payload;
28
- try {
29
- payload = await response.json();
30
- }
31
- catch (err) {
32
- if (response.ok) {
33
- throw new errors_1.RpcError(`invalid JSON response from ${response.url}: ${String(err)}`);
34
- }
35
- payload = await response.text();
36
- }
37
- if (response.ok) {
38
- return payload;
39
- }
40
- let message = 'unknown error';
41
- if (payload && typeof payload === 'object') {
42
- message = payload.error ?? payload.message ?? JSON.stringify(payload, (_k, v) => v);
43
- }
44
- else if (typeof payload === 'string' && payload.trim()) {
45
- message = payload.trim();
46
- }
47
- throw new errors_1.RpcError(`${response.status}: ${message}`);
48
- }
49
- async get(path) {
50
- const resp = await this.fetchFn(`${this.baseUrl}${path}`, {
51
- headers: this.headers(),
52
- method: 'GET',
53
- });
54
- return this.decode(resp);
55
- }
56
- async post(path, body) {
57
- const resp = await this.fetchFn(`${this.baseUrl}${path}`, {
58
- headers: { 'content-type': 'application/json', ...this.headers() },
59
- method: 'POST',
60
- body: JSON.stringify(body),
61
- });
62
- return this.decode(resp);
63
- }
64
- async getPublicParams() {
65
- const data = await this.get('/core/public-params');
66
- return signing_1.CorePublicParameters.fromRpc(data);
67
- }
68
- async issueGuarantee(body) {
69
- return this.post('/core/guarantees', body);
70
- }
71
- async createPaymentTab(body) {
72
- return this.post('/core/payment-tabs', body);
73
- }
74
- async listSettledTabs(recipientAddress) {
75
- return this.get(`/core/recipients/${recipientAddress}/settled-tabs`);
76
- }
77
- async listPendingRemunerations(recipientAddress) {
78
- return this.get(`/core/recipients/${recipientAddress}/pending-remunerations`);
79
- }
80
- async getTab(tabId) {
81
- return this.get(`/core/tabs/${serializeTabId(tabId)}`);
82
- }
83
- async listRecipientTabs(recipientAddress, settlementStatuses) {
84
- let query = '';
85
- if (settlementStatuses?.length) {
86
- query =
87
- '?' + settlementStatuses.map((s) => `settlementStatus=${encodeURIComponent(s)}`).join('&');
88
- }
89
- return this.get(`/core/recipients/${recipientAddress}/tabs${query}`);
90
- }
91
- async getTabGuarantees(tabId) {
92
- return this.get(`/core/tabs/${serializeTabId(tabId)}/guarantees`);
93
- }
94
- async getLatestGuarantee(tabId) {
95
- return this.get(`/core/tabs/${serializeTabId(tabId)}/guarantees/latest`);
96
- }
97
- async getGuarantee(tabId, reqId) {
98
- return this.get(`/core/tabs/${serializeTabId(tabId)}/guarantees/${reqId}`);
99
- }
100
- async listRecipientPayments(recipientAddress) {
101
- return this.get(`/core/recipients/${recipientAddress}/payments`);
102
- }
103
- async getCollateralEventsForTab(tabId) {
104
- return this.get(`/core/tabs/${serializeTabId(tabId)}/collateral-events`);
105
- }
106
- async getUserAssetBalance(userAddress, assetAddress) {
107
- return this.get(`/core/users/${userAddress}/assets/${assetAddress}`);
108
- }
109
- async updateUserSuspension(userAddress, suspended) {
110
- return this.post(`/core/users/${userAddress}/suspension`, { suspended });
111
- }
112
- async createAdminApiKey(body) {
113
- return this.post('/core/admin/api-keys', body);
114
- }
115
- async listAdminApiKeys() {
116
- return this.get('/core/admin/api-keys');
117
- }
118
- async revokeAdminApiKey(keyId) {
119
- return this.post(`/core/admin/api-keys/${keyId}/revoke`, {});
120
- }
121
- }
122
- exports.RpcProxy = RpcProxy;
@@ -1,16 +0,0 @@
1
- import { PaymentGuaranteeRequestClaims, PaymentSignature, SigningScheme } from './models';
2
- export declare class CorePublicParameters {
3
- publicKey: Uint8Array;
4
- contractAddress: string;
5
- ethereumHttpRpcUrl: string;
6
- eip712Name: string;
7
- eip712Version: string;
8
- chainId: number;
9
- constructor(publicKey: Uint8Array, contractAddress: string, ethereumHttpRpcUrl: string, eip712Name: string, eip712Version: string, chainId: number);
10
- static fromRpc(payload: Record<string, any>): CorePublicParameters;
11
- }
12
- export declare class PaymentSigner {
13
- private wallet;
14
- constructor(privateKey: string);
15
- signRequest(params: CorePublicParameters, claims: PaymentGuaranteeRequestClaims, scheme?: SigningScheme): Promise<PaymentSignature>;
16
- }
@@ -1,102 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PaymentSigner = exports.CorePublicParameters = void 0;
4
- const ethers_1 = require("ethers");
5
- const errors_1 = require("./errors");
6
- const models_1 = require("./models");
7
- const utils_1 = require("./utils");
8
- class CorePublicParameters {
9
- constructor(publicKey, contractAddress, ethereumHttpRpcUrl, eip712Name, eip712Version, chainId) {
10
- this.publicKey = publicKey;
11
- this.contractAddress = contractAddress;
12
- this.ethereumHttpRpcUrl = ethereumHttpRpcUrl;
13
- this.eip712Name = eip712Name;
14
- this.eip712Version = eip712Version;
15
- this.chainId = chainId;
16
- }
17
- static fromRpc(payload) {
18
- const pkRaw = payload.public_key ?? payload.publicKey;
19
- const pk = typeof pkRaw === 'string'
20
- ? (0, ethers_1.getBytes)(pkRaw)
21
- : pkRaw
22
- ? Uint8Array.from(pkRaw)
23
- : new Uint8Array();
24
- return new CorePublicParameters(pk, payload.contract_address ?? payload.contractAddress, payload.ethereum_http_rpc_url ?? payload.ethereumHttpRpcUrl, payload.eip712_name ?? payload.eip712Name ?? '4Mica', payload.eip712_version ?? payload.eip712Version ?? '1', Number(payload.chain_id ?? payload.chainId));
25
- }
26
- }
27
- exports.CorePublicParameters = CorePublicParameters;
28
- function buildTypedMessage(params, claims) {
29
- return {
30
- types: {
31
- EIP712Domain: [
32
- { name: 'name', type: 'string' },
33
- { name: 'version', type: 'string' },
34
- { name: 'chainId', type: 'uint256' },
35
- ],
36
- SolGuaranteeRequestClaimsV1: [
37
- { name: 'user', type: 'address' },
38
- { name: 'recipient', type: 'address' },
39
- { name: 'tabId', type: 'uint256' },
40
- { name: 'amount', type: 'uint256' },
41
- { name: 'asset', type: 'address' },
42
- { name: 'timestamp', type: 'uint64' },
43
- ],
44
- },
45
- primaryType: 'SolGuaranteeRequestClaimsV1',
46
- domain: {
47
- name: params.eip712Name,
48
- version: params.eip712Version,
49
- chainId: params.chainId,
50
- },
51
- message: {
52
- user: claims.userAddress,
53
- recipient: claims.recipientAddress,
54
- tabId: Number(claims.tabId),
55
- amount: Number(claims.amount),
56
- asset: claims.assetAddress,
57
- timestamp: Number(claims.timestamp),
58
- },
59
- };
60
- }
61
- function encodeEip191(claims) {
62
- const payload = ethers_1.AbiCoder.defaultAbiCoder().encode(['address', 'address', 'uint256', 'uint256', 'address', 'uint64'], [
63
- claims.userAddress,
64
- claims.recipientAddress,
65
- claims.tabId,
66
- claims.amount,
67
- claims.assetAddress,
68
- claims.timestamp,
69
- ]);
70
- return (0, ethers_1.getBytes)(payload);
71
- }
72
- class PaymentSigner {
73
- constructor(privateKey) {
74
- this.wallet = new ethers_1.Wallet(privateKey);
75
- }
76
- async signRequest(params, claims, scheme = models_1.SigningScheme.EIP712) {
77
- if ((0, utils_1.normalizeAddress)(this.wallet.address) !== (0, utils_1.normalizeAddress)(claims.userAddress)) {
78
- throw new errors_1.SigningError(`address mismatch: signer ${this.wallet.address} != claims.user_address ${claims.userAddress}`);
79
- }
80
- try {
81
- if (scheme === models_1.SigningScheme.EIP712) {
82
- const typed = buildTypedMessage(params, claims);
83
- const claimsTypes = [...typed.types.SolGuaranteeRequestClaimsV1];
84
- const signature = await this.wallet.signTypedData(typed.domain, { SolGuaranteeRequestClaimsV1: claimsTypes }, typed.message);
85
- return { signature, scheme };
86
- }
87
- if (scheme === models_1.SigningScheme.EIP191) {
88
- const message = encodeEip191(claims);
89
- const signature = await this.wallet.signMessage(message);
90
- return { signature, scheme };
91
- }
92
- throw new errors_1.SigningError(`unsupported signing scheme: ${scheme}`);
93
- }
94
- catch (err) {
95
- if (err instanceof utils_1.ValidationError) {
96
- throw new errors_1.SigningError(err.message);
97
- }
98
- throw new errors_1.SigningError(err?.message ?? String(err));
99
- }
100
- }
101
- }
102
- exports.PaymentSigner = PaymentSigner;
@@ -1,8 +0,0 @@
1
- export declare class ValidationError extends Error {
2
- constructor(message: string);
3
- }
4
- export declare function validateUrl(raw: string): string;
5
- export declare function normalizePrivateKey(raw: string): string;
6
- export declare function normalizeAddress(raw: string): string;
7
- export declare function parseU256(value: number | bigint | string): bigint;
8
- export declare function serializeU256(value: number | bigint | string): string;
package/dist/src/utils.js DELETED
@@ -1,78 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ValidationError = void 0;
4
- exports.validateUrl = validateUrl;
5
- exports.normalizePrivateKey = normalizePrivateKey;
6
- exports.normalizeAddress = normalizeAddress;
7
- exports.parseU256 = parseU256;
8
- exports.serializeU256 = serializeU256;
9
- const ethers_1 = require("ethers");
10
- class ValidationError extends Error {
11
- constructor(message) {
12
- super(message);
13
- this.name = 'ValidationError';
14
- }
15
- }
16
- exports.ValidationError = ValidationError;
17
- function validateUrl(raw) {
18
- try {
19
- const url = new URL(raw);
20
- if (!url.protocol || !url.host) {
21
- throw new Error('missing parts');
22
- }
23
- return raw;
24
- }
25
- catch {
26
- throw new ValidationError(`invalid URL: ${raw}`);
27
- }
28
- }
29
- function normalizePrivateKey(raw) {
30
- const key = raw.startsWith('0x') ? raw.slice(2) : raw;
31
- if (!/^[0-9a-fA-F]{64}$/.test(key)) {
32
- throw new ValidationError('invalid private key (expected 32 byte hex)');
33
- }
34
- return `0x${key.toLowerCase()}`;
35
- }
36
- function normalizeAddress(raw) {
37
- const candidate = String(raw);
38
- if ((0, ethers_1.isAddress)(candidate)) {
39
- return (0, ethers_1.getAddress)(candidate);
40
- }
41
- const lower = candidate.toLowerCase();
42
- if ((0, ethers_1.isAddress)(lower)) {
43
- return (0, ethers_1.getAddress)(lower);
44
- }
45
- throw new ValidationError(`invalid address: ${raw}`);
46
- }
47
- function parseNumericString(raw) {
48
- const text = raw.trim();
49
- const n = BigInt(text);
50
- if (n < 0n) {
51
- throw new ValidationError('u256 cannot be negative');
52
- }
53
- return n;
54
- }
55
- function parseU256(value) {
56
- if (typeof value === 'number') {
57
- if (!Number.isFinite(value)) {
58
- throw new ValidationError('invalid integer');
59
- }
60
- if (value < 0) {
61
- throw new ValidationError('u256 cannot be negative');
62
- }
63
- return BigInt(value);
64
- }
65
- if (typeof value === 'bigint') {
66
- if (value < 0) {
67
- throw new ValidationError('u256 cannot be negative');
68
- }
69
- return value;
70
- }
71
- if (typeof value === 'string') {
72
- return parseNumericString(value);
73
- }
74
- throw new ValidationError(`unsupported numeric type: ${typeof value}`);
75
- }
76
- function serializeU256(value) {
77
- return `0x${parseU256(value).toString(16)}`;
78
- }
@@ -1,77 +0,0 @@
1
- import { PaymentGuaranteeRequestClaims, PaymentSignature, SigningScheme } from './models';
2
- import type { FetchFn } from './rpc';
3
- export interface PaymentRequirementsInit {
4
- scheme: string;
5
- network: string;
6
- maxAmountRequired: string;
7
- payTo: string;
8
- asset: string;
9
- extra?: Record<string, any>;
10
- resource?: string;
11
- description?: string;
12
- mimeType?: string;
13
- outputSchema?: any;
14
- maxTimeoutSeconds?: number;
15
- }
16
- export declare class PaymentRequirements {
17
- scheme: string;
18
- network: string;
19
- maxAmountRequired: string;
20
- payTo: string;
21
- asset: string;
22
- extra: Record<string, any>;
23
- resource?: string | undefined;
24
- description?: string | undefined;
25
- mimeType?: string | undefined;
26
- outputSchema?: any | undefined;
27
- maxTimeoutSeconds?: number | undefined;
28
- constructor(scheme: string, network: string, maxAmountRequired: string, payTo: string, asset: string, extra: Record<string, any>, resource?: string | undefined, description?: string | undefined, mimeType?: string | undefined, outputSchema?: any | undefined, maxTimeoutSeconds?: number | undefined);
29
- static fromRaw(raw: Record<string, any>): PaymentRequirements;
30
- toPayload(): Record<string, any>;
31
- }
32
- export declare class PaymentRequirementsExtra {
33
- tabEndpoint?: string | null | undefined;
34
- constructor(tabEndpoint?: string | null | undefined);
35
- static fromRaw(raw: Record<string, any> | undefined): PaymentRequirementsExtra;
36
- }
37
- export declare class TabResponse {
38
- tabId: string;
39
- userAddress: string;
40
- constructor(tabId: string, userAddress: string);
41
- }
42
- export declare class X402PaymentEnvelope {
43
- x402Version: number;
44
- scheme: string;
45
- network: string;
46
- payload: Record<string, any>;
47
- constructor(x402Version: number, scheme: string, network: string, payload: Record<string, any>);
48
- toPayload(): Record<string, any>;
49
- }
50
- export declare class X402SignedPayment {
51
- header: string;
52
- claims: PaymentGuaranteeRequestClaims;
53
- signature: PaymentSignature;
54
- constructor(header: string, claims: PaymentGuaranteeRequestClaims, signature: PaymentSignature);
55
- }
56
- export declare class X402SettledPayment {
57
- payment: X402SignedPayment;
58
- settlement: any;
59
- constructor(payment: X402SignedPayment, settlement: any);
60
- }
61
- export interface FlowSigner {
62
- signPayment(claims: PaymentGuaranteeRequestClaims, scheme: SigningScheme): Promise<PaymentSignature>;
63
- }
64
- export declare class X402Flow {
65
- private signer;
66
- private fetchFn;
67
- constructor(signer: FlowSigner, fetchFn?: FetchFn);
68
- static fromClient(client: {
69
- user: FlowSigner;
70
- }): X402Flow;
71
- signPayment(paymentRequirements: PaymentRequirements, userAddress: string): Promise<X402SignedPayment>;
72
- settlePayment(payment: X402SignedPayment, paymentRequirements: PaymentRequirements, facilitatorUrl: string): Promise<X402SettledPayment>;
73
- protected requestTab(paymentRequirements: PaymentRequirements, userAddress: string): Promise<TabResponse>;
74
- protected buildClaims(requirements: PaymentRequirements, tab: TabResponse, userAddress: string): PaymentGuaranteeRequestClaims;
75
- private static validateScheme;
76
- private static buildEnvelope;
77
- }
package/dist/src/x402.js DELETED
@@ -1,214 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.X402Flow = exports.X402SettledPayment = exports.X402SignedPayment = exports.X402PaymentEnvelope = exports.TabResponse = exports.PaymentRequirementsExtra = exports.PaymentRequirements = void 0;
4
- const models_1 = require("./models");
5
- const utils_1 = require("./utils");
6
- const errors_1 = require("./errors");
7
- class PaymentRequirements {
8
- constructor(scheme, network, maxAmountRequired, payTo, asset, extra, resource, description, mimeType, outputSchema, maxTimeoutSeconds) {
9
- this.scheme = scheme;
10
- this.network = network;
11
- this.maxAmountRequired = maxAmountRequired;
12
- this.payTo = payTo;
13
- this.asset = asset;
14
- this.extra = extra;
15
- this.resource = resource;
16
- this.description = description;
17
- this.mimeType = mimeType;
18
- this.outputSchema = outputSchema;
19
- this.maxTimeoutSeconds = maxTimeoutSeconds;
20
- }
21
- static fromRaw(raw) {
22
- const pick = (keys, defaultValue) => {
23
- for (const key of keys) {
24
- if (raw[key] !== undefined && raw[key] !== null)
25
- return raw[key];
26
- }
27
- return defaultValue;
28
- };
29
- const amount = pick(['maxAmountRequired', 'max_amount_required']);
30
- const payTo = pick(['payTo', 'pay_to']);
31
- const asset = pick(['asset', 'assetAddress', 'asset_address']);
32
- const scheme = pick(['scheme']);
33
- const network = pick(['network']);
34
- if (!amount || !payTo || !asset || !scheme || !network) {
35
- const missing = [
36
- ['scheme', scheme],
37
- ['network', network],
38
- ['maxAmountRequired', amount],
39
- ['payTo', payTo],
40
- ['asset', asset],
41
- ]
42
- .filter(([, value]) => !value)
43
- .map(([key]) => key)
44
- .join(', ');
45
- throw new errors_1.X402Error(`payment requirements missing fields: ${missing}`);
46
- }
47
- return new PaymentRequirements(scheme, network, String(amount), payTo, asset, pick(['extra'], {}) ?? {}, pick(['resource']), pick(['description']), pick(['mimeType', 'mime_type']), pick(['outputSchema', 'output_schema']), pick(['maxTimeoutSeconds', 'max_timeout_seconds']));
48
- }
49
- toPayload() {
50
- const extraPayload = { ...(this.extra ?? {}) };
51
- if ('tab_endpoint' in extraPayload && !('tabEndpoint' in extraPayload)) {
52
- extraPayload['tabEndpoint'] = extraPayload['tab_endpoint'];
53
- delete extraPayload['tab_endpoint'];
54
- }
55
- const payload = {
56
- scheme: this.scheme,
57
- network: this.network,
58
- maxAmountRequired: this.maxAmountRequired,
59
- payTo: this.payTo,
60
- asset: this.asset,
61
- extra: extraPayload,
62
- };
63
- if (this.resource !== undefined)
64
- payload.resource = this.resource;
65
- if (this.description !== undefined)
66
- payload.description = this.description;
67
- if (this.mimeType !== undefined)
68
- payload.mimeType = this.mimeType;
69
- if (this.outputSchema !== undefined)
70
- payload.outputSchema = this.outputSchema;
71
- if (this.maxTimeoutSeconds !== undefined)
72
- payload.maxTimeoutSeconds = this.maxTimeoutSeconds;
73
- return payload;
74
- }
75
- }
76
- exports.PaymentRequirements = PaymentRequirements;
77
- class PaymentRequirementsExtra {
78
- constructor(tabEndpoint) {
79
- this.tabEndpoint = tabEndpoint;
80
- }
81
- static fromRaw(raw) {
82
- const tabEndpoint = raw?.tabEndpoint ?? raw?.tab_endpoint;
83
- return new PaymentRequirementsExtra(tabEndpoint);
84
- }
85
- }
86
- exports.PaymentRequirementsExtra = PaymentRequirementsExtra;
87
- class TabResponse {
88
- constructor(tabId, userAddress) {
89
- this.tabId = tabId;
90
- this.userAddress = userAddress;
91
- }
92
- }
93
- exports.TabResponse = TabResponse;
94
- class X402PaymentEnvelope {
95
- constructor(x402Version, scheme, network, payload) {
96
- this.x402Version = x402Version;
97
- this.scheme = scheme;
98
- this.network = network;
99
- this.payload = payload;
100
- }
101
- toPayload() {
102
- return {
103
- x402Version: this.x402Version,
104
- scheme: this.scheme,
105
- network: this.network,
106
- payload: this.payload,
107
- };
108
- }
109
- }
110
- exports.X402PaymentEnvelope = X402PaymentEnvelope;
111
- class X402SignedPayment {
112
- constructor(header, claims, signature) {
113
- this.header = header;
114
- this.claims = claims;
115
- this.signature = signature;
116
- }
117
- }
118
- exports.X402SignedPayment = X402SignedPayment;
119
- class X402SettledPayment {
120
- constructor(payment, settlement) {
121
- this.payment = payment;
122
- this.settlement = settlement;
123
- }
124
- }
125
- exports.X402SettledPayment = X402SettledPayment;
126
- class X402Flow {
127
- constructor(signer, fetchFn = fetch) {
128
- this.signer = signer;
129
- this.fetchFn = fetchFn;
130
- }
131
- static fromClient(client) {
132
- return new X402Flow(client.user);
133
- }
134
- async signPayment(paymentRequirements, userAddress) {
135
- X402Flow.validateScheme(paymentRequirements.scheme);
136
- const tab = await this.requestTab(paymentRequirements, userAddress);
137
- const claims = this.buildClaims(paymentRequirements, tab, userAddress);
138
- const signature = await this.signer.signPayment(claims, models_1.SigningScheme.EIP712);
139
- const envelope = X402Flow.buildEnvelope(paymentRequirements, claims, signature);
140
- const payload = envelope.toPayload();
141
- payload.x402Version ?? (payload.x402Version = envelope.x402Version);
142
- const header = Buffer.from(JSON.stringify(payload)).toString('base64');
143
- return new X402SignedPayment(header, claims, signature);
144
- }
145
- async settlePayment(payment, paymentRequirements, facilitatorUrl) {
146
- const url = `${facilitatorUrl.replace(/\/$/, '')}/settle`;
147
- const response = await this.fetchFn(url, {
148
- method: 'POST',
149
- headers: { 'content-type': 'application/json' },
150
- body: JSON.stringify({
151
- x402Version: 1,
152
- paymentHeader: payment.header,
153
- paymentRequirements: paymentRequirements.toPayload(),
154
- }),
155
- });
156
- const data = await response.text();
157
- if (!response.ok) {
158
- throw new errors_1.X402Error(`settlement failed with status ${response.status}: ${data}`);
159
- }
160
- const settlement = data ? JSON.parse(data) : {};
161
- return new X402SettledPayment(payment, settlement);
162
- }
163
- async requestTab(paymentRequirements, userAddress) {
164
- const extra = PaymentRequirementsExtra.fromRaw(paymentRequirements.extra);
165
- if (!extra.tabEndpoint) {
166
- throw new errors_1.X402Error('missing tabEndpoint in paymentRequirements.extra');
167
- }
168
- const resp = await this.fetchFn(extra.tabEndpoint, {
169
- method: 'POST',
170
- headers: { 'content-type': 'application/json' },
171
- body: JSON.stringify({
172
- userAddress,
173
- paymentRequirements: paymentRequirements.toPayload(),
174
- }),
175
- });
176
- if (!resp.ok) {
177
- const text = await resp.text();
178
- throw new errors_1.X402Error(`tab resolution failed: ${resp.status} ${text}`);
179
- }
180
- const body = await resp.json();
181
- return new TabResponse(body.tabId ?? body.tab_id, body.userAddress ?? body.user_address);
182
- }
183
- buildClaims(requirements, tab, userAddress) {
184
- const tabId = (0, utils_1.parseU256)(tab.tabId);
185
- const amount = (0, utils_1.parseU256)(requirements.maxAmountRequired);
186
- if (tab.userAddress.toLowerCase() !== userAddress.toLowerCase()) {
187
- throw new errors_1.X402Error(`user mismatch in paymentRequirements: found ${tab.userAddress}, expected ${userAddress}`);
188
- }
189
- const timestamp = Math.floor(Date.now() / 1000);
190
- return models_1.PaymentGuaranteeRequestClaims.new(userAddress, (0, utils_1.normalizeAddress)(requirements.payTo), tabId, amount, timestamp, requirements.asset);
191
- }
192
- static validateScheme(scheme) {
193
- if (!scheme.toLowerCase().includes('4mica')) {
194
- throw new errors_1.X402Error(`invalid scheme: ${scheme}`);
195
- }
196
- }
197
- static buildEnvelope(paymentRequirements, claims, signature) {
198
- const payload = {
199
- claims: {
200
- version: 'v1',
201
- user_address: claims.userAddress,
202
- recipient_address: claims.recipientAddress,
203
- tab_id: `0x${claims.tabId.toString(16)}`,
204
- amount: `0x${claims.amount.toString(16)}`,
205
- asset_address: claims.assetAddress,
206
- timestamp: claims.timestamp,
207
- },
208
- signature: signature.signature,
209
- scheme: signature.scheme,
210
- };
211
- return new X402PaymentEnvelope(1, paymentRequirements.scheme, paymentRequirements.network, payload);
212
- }
213
- }
214
- exports.X402Flow = X402Flow;
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const config_1 = require("../src/config");
5
- const errors_1 = require("../src/errors");
6
- (0, vitest_1.describe)('ConfigBuilder', () => {
7
- (0, vitest_1.beforeEach)(() => {
8
- vitest_1.vi.resetModules();
9
- });
10
- (0, vitest_1.it)('reads from env', () => {
11
- process.env['4MICA_RPC_URL'] = 'https://example.com';
12
- process.env['4MICA_WALLET_PRIVATE_KEY'] = '11'.repeat(32);
13
- const cfg = new config_1.ConfigBuilder().fromEnv().build();
14
- (0, vitest_1.expect)(cfg.rpcUrl).toBe('https://example.com');
15
- (0, vitest_1.expect)(cfg.walletPrivateKey.startsWith('0x11')).toBe(true);
16
- });
17
- (0, vitest_1.it)('requires private key', () => {
18
- delete process.env['4MICA_WALLET_PRIVATE_KEY'];
19
- const builder = new config_1.ConfigBuilder().fromEnv();
20
- (0, vitest_1.expect)(() => builder.build()).toThrow(errors_1.ConfigError);
21
- });
22
- (0, vitest_1.it)('rejects invalid private key', () => {
23
- const builder = new config_1.ConfigBuilder().walletPrivateKey('0x1234');
24
- (0, vitest_1.expect)(() => builder.build()).toThrow(errors_1.ConfigError);
25
- });
26
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const guarantee_1 = require("../src/guarantee");
5
- (0, vitest_1.describe)('guarantee codec', () => {
6
- (0, vitest_1.it)('round trips guarantee claims', () => {
7
- const claims = {
8
- domain: new Uint8Array(32),
9
- userAddress: '0x0000000000000000000000000000000000000001',
10
- recipientAddress: '0x0000000000000000000000000000000000000002',
11
- tabId: 1n,
12
- reqId: 2n,
13
- amount: 3n,
14
- totalAmount: 4n,
15
- assetAddress: '0x0000000000000000000000000000000000000000',
16
- timestamp: 123456,
17
- version: 1,
18
- };
19
- const encoded = (0, guarantee_1.encodeGuaranteeClaims)(claims);
20
- const decoded = (0, guarantee_1.decodeGuaranteeClaims)(encoded);
21
- (0, vitest_1.expect)(decoded.userAddress).toBe(claims.userAddress);
22
- (0, vitest_1.expect)(decoded.recipientAddress).toBe(claims.recipientAddress);
23
- (0, vitest_1.expect)(decoded.tabId).toBe(claims.tabId);
24
- (0, vitest_1.expect)(decoded.amount).toBe(claims.amount);
25
- });
26
- });
@@ -1 +0,0 @@
1
- export {};