@4mica/sdk 0.5.6 → 1.0.1
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 +82 -4
- package/dist/abi/core4mica.d.ts +0 -28
- package/dist/abi/core4mica.js +0 -36
- package/dist/abi/erc20.d.ts +10 -0
- package/dist/abi/erc20.js +13 -0
- package/dist/bls.js +13 -2
- package/dist/client/index.d.ts +48 -1
- package/dist/client/index.js +46 -0
- package/dist/client/recipient.d.ts +108 -4
- package/dist/client/recipient.js +129 -6
- package/dist/client/user.d.ts +78 -2
- package/dist/client/user.js +83 -28
- package/dist/config.d.ts +50 -0
- package/dist/config.js +42 -1
- package/dist/contract.d.ts +10 -0
- package/dist/contract.js +74 -24
- package/dist/errors.d.ts +15 -0
- package/dist/errors.js +15 -0
- package/dist/guarantee.d.ts +22 -0
- package/dist/guarantee.js +209 -29
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/models.d.ts +108 -0
- package/dist/models.js +120 -1
- package/dist/payment.d.ts +66 -4
- package/dist/payment.js +39 -5
- package/dist/rpc.d.ts +2 -2
- package/dist/rpc.js +5 -2
- package/dist/signing.d.ts +89 -12
- package/dist/signing.js +109 -30
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +13 -5
- package/dist/validation.d.ts +32 -0
- package/dist/validation.js +82 -0
- package/dist/x402/index.d.ts +70 -2
- package/dist/x402/index.js +101 -1
- package/dist/x402/models.d.ts +8 -2
- package/package.json +6 -1
package/dist/contract.d.ts
CHANGED
|
@@ -9,16 +9,26 @@ type CoreContract = GetContractReturnType<typeof core4micaAbi, {
|
|
|
9
9
|
export type TxReceiptWaitOptions = {
|
|
10
10
|
timeout?: number;
|
|
11
11
|
pollingInterval?: number;
|
|
12
|
+
gas?: bigint;
|
|
12
13
|
};
|
|
13
14
|
export declare class ContractGateway {
|
|
14
15
|
readonly publicClient: TPublicClient;
|
|
15
16
|
readonly walletClient: TWalletClient;
|
|
16
17
|
readonly contract: CoreContract;
|
|
17
18
|
private erc20Cache;
|
|
19
|
+
private txQueue;
|
|
18
20
|
private constructor();
|
|
19
21
|
static create(rpcUrl: string, signer: Account, contractAddress: Hex, chainId: number): Promise<ContractGateway>;
|
|
20
22
|
private erc20;
|
|
23
|
+
private enqueueTx;
|
|
24
|
+
private defaultFeeParams;
|
|
25
|
+
private splitWaitOptions;
|
|
21
26
|
getGuaranteeDomain(): Promise<string>;
|
|
27
|
+
getGuaranteeVersionConfig(version: number): Promise<{
|
|
28
|
+
domainSeparator: string;
|
|
29
|
+
decoder: string;
|
|
30
|
+
enabled: boolean;
|
|
31
|
+
}>;
|
|
22
32
|
approveErc20(token: string, amount: number | bigint | string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
23
33
|
deposit(amount: number | bigint | string, erc20Token?: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
24
34
|
getUserAssets(): Promise<{
|
package/dist/contract.js
CHANGED
|
@@ -4,12 +4,17 @@ exports.ContractGateway = void 0;
|
|
|
4
4
|
const viem_1 = require("viem");
|
|
5
5
|
const core4mica_1 = require("./abi/core4mica");
|
|
6
6
|
const chain_1 = require("./chain");
|
|
7
|
+
const errors_1 = require("./errors");
|
|
7
8
|
const utils_1 = require("./utils");
|
|
9
|
+
const DEFAULT_REMUNERATE_GAS_LIMIT = 8000000n;
|
|
10
|
+
const DEFAULT_MAX_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
|
|
11
|
+
const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
|
|
8
12
|
class ContractGateway {
|
|
9
13
|
publicClient;
|
|
10
14
|
walletClient;
|
|
11
15
|
contract;
|
|
12
16
|
erc20Cache = new Map();
|
|
17
|
+
txQueue = Promise.resolve();
|
|
13
18
|
constructor(publicClient, walletClient, contract) {
|
|
14
19
|
this.publicClient = publicClient;
|
|
15
20
|
this.walletClient = walletClient;
|
|
@@ -22,7 +27,7 @@ class ContractGateway {
|
|
|
22
27
|
});
|
|
23
28
|
const rpcChainId = await publicClient.getChainId();
|
|
24
29
|
if (rpcChainId !== Number(chainId)) {
|
|
25
|
-
throw new
|
|
30
|
+
throw new errors_1.ContractError(`Connected to chain ${rpcChainId}, expected ${chainId}`);
|
|
26
31
|
}
|
|
27
32
|
const walletClient = (0, viem_1.createWalletClient)({
|
|
28
33
|
transport: (0, viem_1.http)(rpcUrl),
|
|
@@ -49,28 +54,63 @@ class ContractGateway {
|
|
|
49
54
|
}
|
|
50
55
|
return this.erc20Cache.get(token);
|
|
51
56
|
}
|
|
57
|
+
enqueueTx(fn) {
|
|
58
|
+
// Serialize transaction submissions to avoid nonce collisions.
|
|
59
|
+
const run = this.txQueue.then(fn, fn);
|
|
60
|
+
this.txQueue = run.then(() => undefined, () => undefined);
|
|
61
|
+
return run;
|
|
62
|
+
}
|
|
63
|
+
defaultFeeParams() {
|
|
64
|
+
return {
|
|
65
|
+
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
|
66
|
+
maxPriorityFeePerGas: DEFAULT_MAX_PRIORITY_FEE_PER_GAS,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
splitWaitOptions(waitOptions) {
|
|
70
|
+
if (!waitOptions) {
|
|
71
|
+
return { receipt: {} };
|
|
72
|
+
}
|
|
73
|
+
const { gas, timeout, pollingInterval } = waitOptions;
|
|
74
|
+
return {
|
|
75
|
+
gas,
|
|
76
|
+
receipt: {
|
|
77
|
+
...(timeout !== undefined ? { timeout } : {}),
|
|
78
|
+
...(pollingInterval !== undefined ? { pollingInterval } : {}),
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
52
82
|
async getGuaranteeDomain() {
|
|
53
83
|
return this.contract.read.guaranteeDomainSeparator();
|
|
54
84
|
}
|
|
85
|
+
async getGuaranteeVersionConfig(version) {
|
|
86
|
+
const [, domainSeparator, decoder, enabled] = await this.contract.read.getGuaranteeVersionConfig([BigInt(version)]);
|
|
87
|
+
return { domainSeparator: domainSeparator, decoder: decoder, enabled };
|
|
88
|
+
}
|
|
55
89
|
async approveErc20(token, amount, waitOptions) {
|
|
90
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
56
91
|
const erc20 = this.erc20(token);
|
|
57
92
|
// spender address logic
|
|
58
93
|
const spender = this.contract.address;
|
|
59
|
-
const hash = await erc20.write.approve([spender, (0, utils_1.parseU256)(amount)]);
|
|
60
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
94
|
+
const hash = await this.enqueueTx(() => erc20.write.approve([spender, (0, utils_1.parseU256)(amount)], this.defaultFeeParams()));
|
|
95
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
61
96
|
}
|
|
62
97
|
async deposit(amount, erc20Token, waitOptions) {
|
|
98
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
63
99
|
let hash;
|
|
64
100
|
if (erc20Token) {
|
|
65
|
-
hash = await this.contract.write.depositStablecoin([erc20Token, (0, utils_1.parseU256)(amount)]);
|
|
101
|
+
hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, (0, utils_1.parseU256)(amount)], this.defaultFeeParams()));
|
|
66
102
|
}
|
|
67
103
|
else {
|
|
68
|
-
hash = await this.contract.write.deposit({ value: (0, utils_1.parseU256)(amount) });
|
|
104
|
+
hash = await this.enqueueTx(() => this.contract.write.deposit({ value: (0, utils_1.parseU256)(amount), ...this.defaultFeeParams() }));
|
|
69
105
|
}
|
|
70
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
106
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
71
107
|
}
|
|
72
108
|
async getUserAssets() {
|
|
73
|
-
const
|
|
109
|
+
const account = this.walletClient.account;
|
|
110
|
+
if (!account) {
|
|
111
|
+
throw new errors_1.ContractError('wallet client has no account configured');
|
|
112
|
+
}
|
|
113
|
+
const addr = account.address;
|
|
74
114
|
const result = await this.contract.read.getUserAllAssets([addr]);
|
|
75
115
|
return result.map((a) => ({
|
|
76
116
|
asset: a.asset,
|
|
@@ -90,55 +130,62 @@ class ContractGateway {
|
|
|
90
130
|
};
|
|
91
131
|
}
|
|
92
132
|
async payTabEth(tabId, reqId, amount, recipient, waitOptions) {
|
|
133
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
93
134
|
const data = new TextEncoder().encode(`tab_id:${tabId.toString(16)};req_id:${reqId.toString(16)}`);
|
|
94
|
-
const hash = await this.walletClient.sendTransaction({
|
|
135
|
+
const hash = await this.enqueueTx(() => this.walletClient.sendTransaction({
|
|
95
136
|
to: recipient,
|
|
96
137
|
value: (0, utils_1.parseU256)(amount),
|
|
97
138
|
data: (0, utils_1.hexFromBytes)(data),
|
|
98
|
-
|
|
99
|
-
|
|
139
|
+
...this.defaultFeeParams(),
|
|
140
|
+
}));
|
|
141
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
100
142
|
}
|
|
101
143
|
async payTabErc20(tabId, amount, erc20Token, recipient, waitOptions) {
|
|
102
|
-
const
|
|
144
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
145
|
+
const hash = await this.enqueueTx(() => this.contract.write.payTabInERC20Token([
|
|
103
146
|
(0, utils_1.parseU256)(tabId),
|
|
104
147
|
erc20Token,
|
|
105
148
|
(0, utils_1.parseU256)(amount),
|
|
106
149
|
recipient,
|
|
107
|
-
]);
|
|
108
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
150
|
+
], this.defaultFeeParams()));
|
|
151
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
109
152
|
}
|
|
110
153
|
async requestWithdrawal(amount, erc20Token, waitOptions) {
|
|
154
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
111
155
|
const value = (0, utils_1.parseU256)(amount);
|
|
112
156
|
let hash;
|
|
113
157
|
if (erc20Token) {
|
|
114
|
-
hash = await this.contract.write.requestWithdrawal([erc20Token, value]);
|
|
158
|
+
hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([erc20Token, value], this.defaultFeeParams()));
|
|
115
159
|
}
|
|
116
160
|
else {
|
|
117
|
-
hash = await this.contract.write.requestWithdrawal([value]);
|
|
161
|
+
hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([value], this.defaultFeeParams()));
|
|
118
162
|
}
|
|
119
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
163
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
120
164
|
}
|
|
121
165
|
async cancelWithdrawal(erc20Token, waitOptions) {
|
|
166
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
122
167
|
let hash;
|
|
123
168
|
if (erc20Token) {
|
|
124
|
-
hash = await this.contract.write.cancelWithdrawal([erc20Token]);
|
|
169
|
+
hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal([erc20Token], this.defaultFeeParams()));
|
|
125
170
|
}
|
|
126
171
|
else {
|
|
127
|
-
hash = await this.contract.write.cancelWithdrawal();
|
|
172
|
+
hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal(this.defaultFeeParams()));
|
|
128
173
|
}
|
|
129
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
174
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
130
175
|
}
|
|
131
176
|
async finalizeWithdrawal(erc20Token, waitOptions) {
|
|
177
|
+
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
132
178
|
let hash;
|
|
133
179
|
if (erc20Token) {
|
|
134
|
-
hash = await this.contract.write.finalizeWithdrawal([erc20Token]);
|
|
180
|
+
hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal([erc20Token], this.defaultFeeParams()));
|
|
135
181
|
}
|
|
136
182
|
else {
|
|
137
|
-
hash = await this.contract.write.finalizeWithdrawal();
|
|
183
|
+
hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal(this.defaultFeeParams()));
|
|
138
184
|
}
|
|
139
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...
|
|
185
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
140
186
|
}
|
|
141
187
|
async remunerate(claimsBlob, signatureWords, waitOptions) {
|
|
188
|
+
const { gas, receipt } = this.splitWaitOptions(waitOptions);
|
|
142
189
|
const sigStruct = {
|
|
143
190
|
x_c0_a: (0, utils_1.hexFromBytes)(signatureWords[0]),
|
|
144
191
|
x_c0_b: (0, utils_1.hexFromBytes)(signatureWords[1]),
|
|
@@ -149,8 +196,11 @@ class ContractGateway {
|
|
|
149
196
|
y_c1_a: (0, utils_1.hexFromBytes)(signatureWords[6]),
|
|
150
197
|
y_c1_b: (0, utils_1.hexFromBytes)(signatureWords[7]),
|
|
151
198
|
};
|
|
152
|
-
const hash = await this.contract.write.remunerate([(0, utils_1.hexFromBytes)(claimsBlob), sigStruct]
|
|
153
|
-
|
|
199
|
+
const hash = await this.enqueueTx(() => this.contract.write.remunerate([(0, utils_1.hexFromBytes)(claimsBlob), sigStruct], {
|
|
200
|
+
gas: gas ?? DEFAULT_REMUNERATE_GAS_LIMIT,
|
|
201
|
+
...this.defaultFeeParams(),
|
|
202
|
+
}));
|
|
203
|
+
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
154
204
|
}
|
|
155
205
|
}
|
|
156
206
|
exports.ContractGateway = ContractGateway;
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/** Base class for all 4Mica SDK errors. Sets `error.name` to the subclass name. */
|
|
1
2
|
export declare class FourMicaError extends Error {
|
|
2
3
|
constructor(message: string);
|
|
3
4
|
}
|
|
5
|
+
/** Thrown when the SDK configuration is invalid (e.g. missing required fields or bad URL). */
|
|
4
6
|
export declare class ConfigError extends FourMicaError {
|
|
5
7
|
}
|
|
8
|
+
/** Thrown when a 4Mica core RPC call fails. Includes the HTTP status and raw response body. */
|
|
6
9
|
export declare class RpcError extends FourMicaError {
|
|
7
10
|
readonly status?: number;
|
|
8
11
|
readonly body?: unknown;
|
|
@@ -11,24 +14,34 @@ export declare class RpcError extends FourMicaError {
|
|
|
11
14
|
body?: unknown;
|
|
12
15
|
});
|
|
13
16
|
}
|
|
17
|
+
/** Thrown when the SDK client fails to initialise (e.g. chain ID mismatch). */
|
|
14
18
|
export declare class ClientInitializationError extends FourMicaError {
|
|
15
19
|
}
|
|
20
|
+
/** Thrown when signing a payment claim fails (e.g. unsupported scheme, address mismatch). */
|
|
16
21
|
export declare class SigningError extends FourMicaError {
|
|
17
22
|
}
|
|
23
|
+
/** Thrown when an on-chain contract call fails or returns an unexpected result. */
|
|
18
24
|
export declare class ContractError extends FourMicaError {
|
|
19
25
|
}
|
|
26
|
+
/** Thrown when BLS certificate verification fails (e.g. domain mismatch, invalid encoding). */
|
|
20
27
|
export declare class VerificationError extends FourMicaError {
|
|
21
28
|
}
|
|
29
|
+
/** Thrown when an x402 HTTP payment flow encounters an error. */
|
|
22
30
|
export declare class X402Error extends FourMicaError {
|
|
23
31
|
}
|
|
32
|
+
/** Base class for authentication-related errors. */
|
|
24
33
|
export declare class AuthError extends FourMicaError {
|
|
25
34
|
}
|
|
35
|
+
/** Thrown when the auth URL is invalid or unreachable. */
|
|
26
36
|
export declare class AuthUrlError extends AuthError {
|
|
27
37
|
}
|
|
38
|
+
/** Thrown when a network-level error occurs during authentication. */
|
|
28
39
|
export declare class AuthTransportError extends AuthError {
|
|
29
40
|
}
|
|
41
|
+
/** Thrown when the auth server response cannot be decoded. */
|
|
30
42
|
export declare class AuthDecodeError extends AuthError {
|
|
31
43
|
}
|
|
44
|
+
/** Thrown when the auth server returns an error response. Includes HTTP status and body. */
|
|
32
45
|
export declare class AuthApiError extends AuthError {
|
|
33
46
|
readonly status?: number;
|
|
34
47
|
readonly body?: unknown;
|
|
@@ -37,7 +50,9 @@ export declare class AuthApiError extends AuthError {
|
|
|
37
50
|
body?: unknown;
|
|
38
51
|
});
|
|
39
52
|
}
|
|
53
|
+
/** Thrown when auth configuration is invalid. */
|
|
40
54
|
export declare class AuthConfigError extends AuthError {
|
|
41
55
|
}
|
|
56
|
+
/** Thrown when an authenticated operation is attempted without auth being configured. */
|
|
42
57
|
export declare class AuthMissingConfigError extends AuthConfigError {
|
|
43
58
|
}
|
package/dist/errors.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.AuthMissingConfigError = exports.AuthConfigError = exports.AuthApiError = exports.AuthDecodeError = exports.AuthTransportError = exports.AuthUrlError = exports.AuthError = exports.X402Error = exports.VerificationError = exports.ContractError = exports.SigningError = exports.ClientInitializationError = exports.RpcError = exports.ConfigError = exports.FourMicaError = void 0;
|
|
4
|
+
/** Base class for all 4Mica SDK errors. Sets `error.name` to the subclass name. */
|
|
4
5
|
class FourMicaError extends Error {
|
|
5
6
|
constructor(message) {
|
|
6
7
|
super(message);
|
|
@@ -8,9 +9,11 @@ class FourMicaError extends Error {
|
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
exports.FourMicaError = FourMicaError;
|
|
12
|
+
/** Thrown when the SDK configuration is invalid (e.g. missing required fields or bad URL). */
|
|
11
13
|
class ConfigError extends FourMicaError {
|
|
12
14
|
}
|
|
13
15
|
exports.ConfigError = ConfigError;
|
|
16
|
+
/** Thrown when a 4Mica core RPC call fails. Includes the HTTP status and raw response body. */
|
|
14
17
|
class RpcError extends FourMicaError {
|
|
15
18
|
status;
|
|
16
19
|
body;
|
|
@@ -21,33 +24,43 @@ class RpcError extends FourMicaError {
|
|
|
21
24
|
}
|
|
22
25
|
}
|
|
23
26
|
exports.RpcError = RpcError;
|
|
27
|
+
/** Thrown when the SDK client fails to initialise (e.g. chain ID mismatch). */
|
|
24
28
|
class ClientInitializationError extends FourMicaError {
|
|
25
29
|
}
|
|
26
30
|
exports.ClientInitializationError = ClientInitializationError;
|
|
31
|
+
/** Thrown when signing a payment claim fails (e.g. unsupported scheme, address mismatch). */
|
|
27
32
|
class SigningError extends FourMicaError {
|
|
28
33
|
}
|
|
29
34
|
exports.SigningError = SigningError;
|
|
35
|
+
/** Thrown when an on-chain contract call fails or returns an unexpected result. */
|
|
30
36
|
class ContractError extends FourMicaError {
|
|
31
37
|
}
|
|
32
38
|
exports.ContractError = ContractError;
|
|
39
|
+
/** Thrown when BLS certificate verification fails (e.g. domain mismatch, invalid encoding). */
|
|
33
40
|
class VerificationError extends FourMicaError {
|
|
34
41
|
}
|
|
35
42
|
exports.VerificationError = VerificationError;
|
|
43
|
+
/** Thrown when an x402 HTTP payment flow encounters an error. */
|
|
36
44
|
class X402Error extends FourMicaError {
|
|
37
45
|
}
|
|
38
46
|
exports.X402Error = X402Error;
|
|
47
|
+
/** Base class for authentication-related errors. */
|
|
39
48
|
class AuthError extends FourMicaError {
|
|
40
49
|
}
|
|
41
50
|
exports.AuthError = AuthError;
|
|
51
|
+
/** Thrown when the auth URL is invalid or unreachable. */
|
|
42
52
|
class AuthUrlError extends AuthError {
|
|
43
53
|
}
|
|
44
54
|
exports.AuthUrlError = AuthUrlError;
|
|
55
|
+
/** Thrown when a network-level error occurs during authentication. */
|
|
45
56
|
class AuthTransportError extends AuthError {
|
|
46
57
|
}
|
|
47
58
|
exports.AuthTransportError = AuthTransportError;
|
|
59
|
+
/** Thrown when the auth server response cannot be decoded. */
|
|
48
60
|
class AuthDecodeError extends AuthError {
|
|
49
61
|
}
|
|
50
62
|
exports.AuthDecodeError = AuthDecodeError;
|
|
63
|
+
/** Thrown when the auth server returns an error response. Includes HTTP status and body. */
|
|
51
64
|
class AuthApiError extends AuthError {
|
|
52
65
|
status;
|
|
53
66
|
body;
|
|
@@ -58,9 +71,11 @@ class AuthApiError extends AuthError {
|
|
|
58
71
|
}
|
|
59
72
|
}
|
|
60
73
|
exports.AuthApiError = AuthApiError;
|
|
74
|
+
/** Thrown when auth configuration is invalid. */
|
|
61
75
|
class AuthConfigError extends AuthError {
|
|
62
76
|
}
|
|
63
77
|
exports.AuthConfigError = AuthConfigError;
|
|
78
|
+
/** Thrown when an authenticated operation is attempted without auth being configured. */
|
|
64
79
|
class AuthMissingConfigError extends AuthConfigError {
|
|
65
80
|
}
|
|
66
81
|
exports.AuthMissingConfigError = AuthMissingConfigError;
|
package/dist/guarantee.d.ts
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
1
|
import { PaymentGuaranteeClaims } from './models';
|
|
2
|
+
/**
|
|
3
|
+
* ABI-encode a {@link PaymentGuaranteeClaims} object into a hex string.
|
|
4
|
+
*
|
|
5
|
+
* Produces the outer `(uint64 version, bytes innerClaims)` envelope format expected
|
|
6
|
+
* by the Core4Mica contract. Supports V1 (10 fields) and V2 (18 fields with validation policy).
|
|
7
|
+
*
|
|
8
|
+
* @param claims - Decoded claims to encode. Must have `version` set to `1` or `2`.
|
|
9
|
+
* @returns `0x`-prefixed hex string of the ABI-encoded envelope.
|
|
10
|
+
* @throws {@link VerificationError} if `version` is not `1` or `2`, the domain is not 32 bytes,
|
|
11
|
+
* or V2 claims are missing `validationPolicy`.
|
|
12
|
+
*/
|
|
2
13
|
export declare function encodeGuaranteeClaims(claims: PaymentGuaranteeClaims): string;
|
|
14
|
+
/**
|
|
15
|
+
* Decode ABI-encoded guarantee claims into a {@link PaymentGuaranteeClaims} object.
|
|
16
|
+
*
|
|
17
|
+
* Accepts either the modern `(uint64 version, bytes innerClaims)` envelope or the legacy
|
|
18
|
+
* unwrapped V1 format (raw 320-byte ABI encoding without an outer envelope).
|
|
19
|
+
*
|
|
20
|
+
* @param data - Hex string or raw bytes of the ABI-encoded claims.
|
|
21
|
+
* @returns Decoded {@link PaymentGuaranteeClaims} with `version` set to `1` or `2`.
|
|
22
|
+
* @throws {@link VerificationError} if the data is too short, the inner length is wrong,
|
|
23
|
+
* or the encoded version number is unsupported.
|
|
24
|
+
*/
|
|
3
25
|
export declare function decodeGuaranteeClaims(data: string | Uint8Array): PaymentGuaranteeClaims;
|
package/dist/guarantee.js
CHANGED
|
@@ -6,7 +6,8 @@ const viem_1 = require("viem");
|
|
|
6
6
|
const errors_1 = require("./errors");
|
|
7
7
|
const utils_1 = require("./utils");
|
|
8
8
|
const CLAIMS_ENCODED_BYTES = 32 * 10;
|
|
9
|
-
|
|
9
|
+
// Minimum bytes for a valid outer envelope: uint64 + bytes offset + bytes length
|
|
10
|
+
const MIN_ENVELOPE_BYTES = 32 * 2 + 32;
|
|
10
11
|
const CLAIM_TYPES = [
|
|
11
12
|
{ type: 'bytes32' },
|
|
12
13
|
{ type: 'uint256' },
|
|
@@ -19,6 +20,54 @@ const CLAIM_TYPES = [
|
|
|
19
20
|
{ type: 'uint64' },
|
|
20
21
|
{ type: 'uint64' },
|
|
21
22
|
];
|
|
23
|
+
// V2 adds: validation_registry_address, validation_request_hash, validation_chain_id,
|
|
24
|
+
// validator_address, validator_agent_id, min_validation_score,
|
|
25
|
+
// validation_subject_hash, required_validation_tag (dynamic string)
|
|
26
|
+
const CLAIM_TYPES_V2 = [
|
|
27
|
+
{ type: 'bytes32' }, // domain
|
|
28
|
+
{ type: 'uint256' }, // tab_id
|
|
29
|
+
{ type: 'uint256' }, // req_id
|
|
30
|
+
{ type: 'address' }, // client (user)
|
|
31
|
+
{ type: 'address' }, // recipient
|
|
32
|
+
{ type: 'uint256' }, // amount
|
|
33
|
+
{ type: 'uint256' }, // total_amount
|
|
34
|
+
{ type: 'address' }, // asset
|
|
35
|
+
{ type: 'uint64' }, // timestamp
|
|
36
|
+
{ type: 'uint64' }, // version
|
|
37
|
+
{ type: 'address' }, // validation_registry_address
|
|
38
|
+
{ type: 'bytes32' }, // validation_request_hash
|
|
39
|
+
{ type: 'uint64' }, // validation_chain_id
|
|
40
|
+
{ type: 'address' }, // validator_address
|
|
41
|
+
{ type: 'uint256' }, // validator_agent_id
|
|
42
|
+
{ type: 'uint8' }, // min_validation_score
|
|
43
|
+
{ type: 'bytes32' }, // validation_subject_hash
|
|
44
|
+
{ type: 'string' }, // required_validation_tag (dynamic)
|
|
45
|
+
];
|
|
46
|
+
const CLAIM_TYPES_V2_TUPLE = [
|
|
47
|
+
{
|
|
48
|
+
type: 'tuple',
|
|
49
|
+
components: [
|
|
50
|
+
{ name: 'domain', type: 'bytes32' },
|
|
51
|
+
{ name: 'tabId', type: 'uint256' },
|
|
52
|
+
{ name: 'reqId', type: 'uint256' },
|
|
53
|
+
{ name: 'user', type: 'address' },
|
|
54
|
+
{ name: 'recipient', type: 'address' },
|
|
55
|
+
{ name: 'amount', type: 'uint256' },
|
|
56
|
+
{ name: 'totalAmount', type: 'uint256' },
|
|
57
|
+
{ name: 'asset', type: 'address' },
|
|
58
|
+
{ name: 'timestamp', type: 'uint64' },
|
|
59
|
+
{ name: 'claimsVersion', type: 'uint64' },
|
|
60
|
+
{ name: 'validationRegistryAddress', type: 'address' },
|
|
61
|
+
{ name: 'validationRequestHash', type: 'bytes32' },
|
|
62
|
+
{ name: 'validationChainId', type: 'uint64' },
|
|
63
|
+
{ name: 'validatorAddress', type: 'address' },
|
|
64
|
+
{ name: 'validatorAgentId', type: 'uint256' },
|
|
65
|
+
{ name: 'minValidationScore', type: 'uint8' },
|
|
66
|
+
{ name: 'validationSubjectHash', type: 'bytes32' },
|
|
67
|
+
{ name: 'requiredValidationTag', type: 'string' },
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
];
|
|
22
71
|
function ensureDomainBytes(domain) {
|
|
23
72
|
const bytes = typeof domain === 'string' ? (0, viem_1.toBytes)(domain) : domain;
|
|
24
73
|
if (bytes.length !== 32) {
|
|
@@ -28,47 +77,115 @@ function ensureDomainBytes(domain) {
|
|
|
28
77
|
}
|
|
29
78
|
function normalizeHexBytes(data) {
|
|
30
79
|
if (typeof data === 'string') {
|
|
31
|
-
return (
|
|
80
|
+
return (0, utils_1.ensureHexPrefix)(data);
|
|
32
81
|
}
|
|
33
82
|
return (0, utils_1.hexFromBytes)(data);
|
|
34
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* ABI-encode a {@link PaymentGuaranteeClaims} object into a hex string.
|
|
86
|
+
*
|
|
87
|
+
* Produces the outer `(uint64 version, bytes innerClaims)` envelope format expected
|
|
88
|
+
* by the Core4Mica contract. Supports V1 (10 fields) and V2 (18 fields with validation policy).
|
|
89
|
+
*
|
|
90
|
+
* @param claims - Decoded claims to encode. Must have `version` set to `1` or `2`.
|
|
91
|
+
* @returns `0x`-prefixed hex string of the ABI-encoded envelope.
|
|
92
|
+
* @throws {@link VerificationError} if `version` is not `1` or `2`, the domain is not 32 bytes,
|
|
93
|
+
* or V2 claims are missing `validationPolicy`.
|
|
94
|
+
*/
|
|
35
95
|
function encodeGuaranteeClaims(claims) {
|
|
36
|
-
if (claims.version
|
|
37
|
-
|
|
96
|
+
if (claims.version === 1) {
|
|
97
|
+
const domain = ensureDomainBytes(claims.domain);
|
|
98
|
+
const encoded = (0, viem_1.encodeAbiParameters)(CLAIM_TYPES, [
|
|
99
|
+
(0, utils_1.hexFromBytes)(domain),
|
|
100
|
+
(0, utils_1.parseU256)(claims.tabId),
|
|
101
|
+
(0, utils_1.parseU256)(claims.reqId),
|
|
102
|
+
claims.userAddress,
|
|
103
|
+
claims.recipientAddress,
|
|
104
|
+
(0, utils_1.parseU256)(claims.amount),
|
|
105
|
+
(0, utils_1.parseU256)(claims.totalAmount),
|
|
106
|
+
claims.assetAddress,
|
|
107
|
+
BigInt(claims.timestamp),
|
|
108
|
+
BigInt(claims.version),
|
|
109
|
+
]);
|
|
110
|
+
return (0, viem_1.encodeAbiParameters)([{ type: 'uint64' }, { type: 'bytes' }], [BigInt(claims.version), encoded]);
|
|
111
|
+
}
|
|
112
|
+
if (claims.version === 2) {
|
|
113
|
+
if (!claims.validationPolicy) {
|
|
114
|
+
throw new errors_1.VerificationError('V2 guarantee claims missing validationPolicy');
|
|
115
|
+
}
|
|
116
|
+
const p = claims.validationPolicy;
|
|
117
|
+
const domain = ensureDomainBytes(claims.domain);
|
|
118
|
+
const encoded = (0, viem_1.encodeAbiParameters)(CLAIM_TYPES_V2_TUPLE, [
|
|
119
|
+
{
|
|
120
|
+
domain: (0, utils_1.hexFromBytes)(domain),
|
|
121
|
+
tabId: (0, utils_1.parseU256)(claims.tabId),
|
|
122
|
+
reqId: (0, utils_1.parseU256)(claims.reqId),
|
|
123
|
+
user: claims.userAddress,
|
|
124
|
+
recipient: claims.recipientAddress,
|
|
125
|
+
amount: (0, utils_1.parseU256)(claims.amount),
|
|
126
|
+
totalAmount: (0, utils_1.parseU256)(claims.totalAmount),
|
|
127
|
+
asset: claims.assetAddress,
|
|
128
|
+
timestamp: BigInt(claims.timestamp),
|
|
129
|
+
claimsVersion: BigInt(claims.version),
|
|
130
|
+
validationRegistryAddress: p.validationRegistryAddress,
|
|
131
|
+
validationRequestHash: (0, utils_1.ensureHexPrefix)(p.validationRequestHash),
|
|
132
|
+
validationChainId: BigInt(p.validationChainId),
|
|
133
|
+
validatorAddress: p.validatorAddress,
|
|
134
|
+
validatorAgentId: p.validatorAgentId,
|
|
135
|
+
minValidationScore: p.minValidationScore,
|
|
136
|
+
validationSubjectHash: (0, utils_1.ensureHexPrefix)(p.validationSubjectHash),
|
|
137
|
+
requiredValidationTag: p.requiredValidationTag,
|
|
138
|
+
},
|
|
139
|
+
]);
|
|
140
|
+
return (0, viem_1.encodeAbiParameters)([{ type: 'uint64' }, { type: 'bytes' }], [BigInt(claims.version), encoded]);
|
|
38
141
|
}
|
|
39
|
-
|
|
40
|
-
const encoded = (0, viem_1.encodeAbiParameters)(CLAIM_TYPES, [
|
|
41
|
-
(0, utils_1.hexFromBytes)(domain),
|
|
42
|
-
(0, utils_1.parseU256)(claims.tabId),
|
|
43
|
-
(0, utils_1.parseU256)(claims.reqId),
|
|
44
|
-
claims.userAddress,
|
|
45
|
-
claims.recipientAddress,
|
|
46
|
-
(0, utils_1.parseU256)(claims.amount),
|
|
47
|
-
(0, utils_1.parseU256)(claims.totalAmount),
|
|
48
|
-
claims.assetAddress,
|
|
49
|
-
BigInt(claims.timestamp),
|
|
50
|
-
BigInt(claims.version),
|
|
51
|
-
]);
|
|
52
|
-
return (0, viem_1.encodeAbiParameters)([{ type: 'uint64' }, { type: 'bytes' }], [BigInt(claims.version), encoded]);
|
|
142
|
+
throw new errors_1.VerificationError(`unsupported guarantee claims version: ${claims.version}`);
|
|
53
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Decode ABI-encoded guarantee claims into a {@link PaymentGuaranteeClaims} object.
|
|
146
|
+
*
|
|
147
|
+
* Accepts either the modern `(uint64 version, bytes innerClaims)` envelope or the legacy
|
|
148
|
+
* unwrapped V1 format (raw 320-byte ABI encoding without an outer envelope).
|
|
149
|
+
*
|
|
150
|
+
* @param data - Hex string or raw bytes of the ABI-encoded claims.
|
|
151
|
+
* @returns Decoded {@link PaymentGuaranteeClaims} with `version` set to `1` or `2`.
|
|
152
|
+
* @throws {@link VerificationError} if the data is too short, the inner length is wrong,
|
|
153
|
+
* or the encoded version number is unsupported.
|
|
154
|
+
*/
|
|
54
155
|
function decodeGuaranteeClaims(data) {
|
|
55
156
|
const hex = normalizeHexBytes(data);
|
|
56
157
|
const byteLen = (hex.length - 2) / 2;
|
|
57
|
-
|
|
158
|
+
// Try to decode as unwrapped V1 (legacy)
|
|
58
159
|
if (byteLen === CLAIMS_ENCODED_BYTES) {
|
|
59
|
-
|
|
160
|
+
return decodeV1Claims(hex);
|
|
60
161
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
162
|
+
// Decode outer envelope to get version
|
|
163
|
+
if (byteLen < MIN_ENVELOPE_BYTES) {
|
|
164
|
+
throw new errors_1.VerificationError(`unexpected guarantee claims length: ${byteLen} bytes`);
|
|
165
|
+
}
|
|
166
|
+
const [version, wrapped] = (0, viem_1.decodeAbiParameters)([{ type: 'uint64' }, { type: 'bytes' }], hex);
|
|
167
|
+
if (version === 1n) {
|
|
168
|
+
const innerHex = wrapped;
|
|
169
|
+
const innerByteLen = (innerHex.length - 2) / 2;
|
|
170
|
+
if (innerByteLen !== CLAIMS_ENCODED_BYTES) {
|
|
171
|
+
throw new errors_1.VerificationError(`unexpected V1 claims inner length: ${innerByteLen} bytes`);
|
|
68
172
|
}
|
|
69
|
-
|
|
173
|
+
return decodeV1Claims(innerHex);
|
|
70
174
|
}
|
|
71
|
-
|
|
175
|
+
if (version === 2n) {
|
|
176
|
+
return decodeV2Claims(wrapped);
|
|
177
|
+
}
|
|
178
|
+
throw new errors_1.VerificationError(`unsupported guarantee claims version: ${version}`);
|
|
179
|
+
}
|
|
180
|
+
function decodeV1Claims(encoded) {
|
|
181
|
+
let decoded;
|
|
182
|
+
try {
|
|
183
|
+
decoded = (0, viem_1.decodeAbiParameters)(CLAIM_TYPES, encoded);
|
|
184
|
+
}
|
|
185
|
+
catch (err) {
|
|
186
|
+
throw new errors_1.VerificationError(`failed to decode V1 guarantee claims: ${String(err)}`);
|
|
187
|
+
}
|
|
188
|
+
const [domain, tabId, reqId, user, recipient, amount, totalAmount, asset, timestamp, claimsVersion,] = decoded;
|
|
72
189
|
if (claimsVersion !== 1n) {
|
|
73
190
|
throw new errors_1.VerificationError(`unsupported guarantee claims version: ${claimsVersion}`);
|
|
74
191
|
}
|
|
@@ -85,3 +202,66 @@ function decodeGuaranteeClaims(data) {
|
|
|
85
202
|
version: Number(claimsVersion),
|
|
86
203
|
};
|
|
87
204
|
}
|
|
205
|
+
function decodeV2Claims(encoded) {
|
|
206
|
+
try {
|
|
207
|
+
const [decoded] = (0, viem_1.decodeAbiParameters)(CLAIM_TYPES_V2_TUPLE, encoded);
|
|
208
|
+
return buildDecodedV2Claims(decoded);
|
|
209
|
+
}
|
|
210
|
+
catch (tupleErr) {
|
|
211
|
+
try {
|
|
212
|
+
const decoded = (0, viem_1.decodeAbiParameters)(CLAIM_TYPES_V2, encoded);
|
|
213
|
+
return buildDecodedV2Claims({
|
|
214
|
+
domain: decoded[0],
|
|
215
|
+
tabId: decoded[1],
|
|
216
|
+
reqId: decoded[2],
|
|
217
|
+
user: decoded[3],
|
|
218
|
+
recipient: decoded[4],
|
|
219
|
+
amount: decoded[5],
|
|
220
|
+
totalAmount: decoded[6],
|
|
221
|
+
asset: decoded[7],
|
|
222
|
+
timestamp: decoded[8],
|
|
223
|
+
claimsVersion: decoded[9],
|
|
224
|
+
validationRegistryAddress: decoded[10],
|
|
225
|
+
validationRequestHash: decoded[11],
|
|
226
|
+
validationChainId: decoded[12],
|
|
227
|
+
validatorAddress: decoded[13],
|
|
228
|
+
validatorAgentId: decoded[14],
|
|
229
|
+
minValidationScore: decoded[15],
|
|
230
|
+
validationSubjectHash: decoded[16],
|
|
231
|
+
requiredValidationTag: decoded[17],
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
catch (flatErr) {
|
|
235
|
+
throw new errors_1.VerificationError(`failed to decode V2 guarantee claims: ${String(tupleErr)}; fallback decode failed: ${String(flatErr)}`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
function buildDecodedV2Claims(decoded) {
|
|
240
|
+
const { domain, tabId, reqId, user, recipient, amount, totalAmount, asset, timestamp, claimsVersion, validationRegistryAddress, validationRequestHash, validationChainId, validatorAddress, validatorAgentId, minValidationScore, validationSubjectHash, requiredValidationTag, } = decoded;
|
|
241
|
+
if (claimsVersion !== 2n) {
|
|
242
|
+
throw new errors_1.VerificationError(`expected V2 claims version, got: ${claimsVersion}`);
|
|
243
|
+
}
|
|
244
|
+
const validationPolicy = {
|
|
245
|
+
validationRegistryAddress: validationRegistryAddress,
|
|
246
|
+
validationRequestHash: validationRequestHash,
|
|
247
|
+
validationChainId: Number(validationChainId),
|
|
248
|
+
validatorAddress: validatorAddress,
|
|
249
|
+
validatorAgentId: (0, utils_1.parseU256)(validatorAgentId),
|
|
250
|
+
minValidationScore: Number(minValidationScore),
|
|
251
|
+
validationSubjectHash: validationSubjectHash,
|
|
252
|
+
requiredValidationTag: requiredValidationTag,
|
|
253
|
+
};
|
|
254
|
+
return {
|
|
255
|
+
domain: (0, viem_1.toBytes)(domain),
|
|
256
|
+
userAddress: user,
|
|
257
|
+
recipientAddress: recipient,
|
|
258
|
+
tabId: (0, utils_1.parseU256)(tabId),
|
|
259
|
+
reqId: (0, utils_1.parseU256)(reqId),
|
|
260
|
+
amount: (0, utils_1.parseU256)(amount),
|
|
261
|
+
totalAmount: (0, utils_1.parseU256)(totalAmount),
|
|
262
|
+
assetAddress: asset,
|
|
263
|
+
timestamp: Number(timestamp),
|
|
264
|
+
version: Number(claimsVersion),
|
|
265
|
+
validationPolicy,
|
|
266
|
+
};
|
|
267
|
+
}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -20,6 +20,7 @@ __exportStar(require("./config"), exports);
|
|
|
20
20
|
__exportStar(require("./utils"), exports);
|
|
21
21
|
__exportStar(require("./models"), exports);
|
|
22
22
|
__exportStar(require("./payment"), exports);
|
|
23
|
+
__exportStar(require("./validation"), exports);
|
|
23
24
|
__exportStar(require("./signing"), exports);
|
|
24
25
|
__exportStar(require("./rpc"), exports);
|
|
25
26
|
__exportStar(require("./auth"), exports);
|