@4mica/sdk 1.2.17 → 1.3.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 +59 -25
- package/dist/index.cjs +5513 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2730 -0
- package/dist/{src/abi/core4mica.d.ts → index.d.ts} +1032 -1
- package/dist/index.js +5439 -0
- package/dist/index.js.map +1 -0
- package/dist/models-B15ouNYG.d.cts +386 -0
- package/dist/models-B15ouNYG.d.ts +386 -0
- package/dist/server.cjs +172 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +119 -0
- package/dist/server.d.ts +119 -0
- package/dist/server.js +165 -0
- package/dist/server.js.map +1 -0
- package/package.json +52 -43
- package/dist/package.json +0 -80
- package/dist/src/abi/core4mica.js +0 -2200
- package/dist/src/abi/erc20.d.ts +0 -151
- package/dist/src/abi/erc20.js +0 -201
- package/dist/src/auth.d.ts +0 -62
- package/dist/src/auth.js +0 -218
- package/dist/src/bls.d.ts +0 -6
- package/dist/src/bls.js +0 -247
- package/dist/src/chain.d.ts +0 -2
- package/dist/src/chain.js +0 -26
- package/dist/src/client/index.d.ts +0 -71
- package/dist/src/client/index.js +0 -120
- package/dist/src/client/recipient.d.ts +0 -129
- package/dist/src/client/recipient.js +0 -257
- package/dist/src/client/shared.d.ts +0 -11
- package/dist/src/client/shared.js +0 -17
- package/dist/src/client/user.d.ts +0 -109
- package/dist/src/client/user.js +0 -151
- package/dist/src/config.d.ts +0 -103
- package/dist/src/config.js +0 -197
- package/dist/src/constants.d.ts +0 -4
- package/dist/src/constants.js +0 -7
- package/dist/src/contract.d.ts +0 -55
- package/dist/src/contract.js +0 -312
- package/dist/src/debug.d.ts +0 -2
- package/dist/src/debug.js +0 -5
- package/dist/src/errors.d.ts +0 -58
- package/dist/src/errors.js +0 -81
- package/dist/src/guarantee.d.ts +0 -25
- package/dist/src/guarantee.js +0 -272
- package/dist/src/http.d.ts +0 -11
- package/dist/src/http.js +0 -57
- package/dist/src/index.d.ts +0 -17
- package/dist/src/index.js +0 -33
- package/dist/src/models.d.ts +0 -261
- package/dist/src/models.js +0 -360
- package/dist/src/networks.d.ts +0 -40
- package/dist/src/networks.js +0 -57
- package/dist/src/payment.d.ts +0 -82
- package/dist/src/payment.js +0 -67
- package/dist/src/rpc.d.ts +0 -38
- package/dist/src/rpc.js +0 -161
- package/dist/src/serde.d.ts +0 -5
- package/dist/src/serde.js +0 -33
- package/dist/src/signing.d.ts +0 -170
- package/dist/src/signing.js +0 -311
- package/dist/src/utils.d.ts +0 -11
- package/dist/src/utils.js +0 -90
- package/dist/src/validation.d.ts +0 -32
- package/dist/src/validation.js +0 -84
- package/dist/src/wallet/cdp.d.ts +0 -13
- package/dist/src/wallet/cdp.js +0 -78
- package/dist/src/wallet/index.d.ts +0 -2
- package/dist/src/wallet/index.js +0 -5
- package/dist/src/x402/index.d.ts +0 -90
- package/dist/src/x402/index.js +0 -243
- package/dist/src/x402/models.d.ts +0 -75
- package/dist/src/x402/models.js +0 -2
package/dist/src/config.js
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ConfigBuilder = void 0;
|
|
4
|
-
const accounts_1 = require("viem/accounts");
|
|
5
|
-
const errors_1 = require("./errors");
|
|
6
|
-
const utils_1 = require("./utils");
|
|
7
|
-
const networks_1 = require("./networks");
|
|
8
|
-
/**
|
|
9
|
-
* Fluent builder for {@link Config}.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```ts
|
|
13
|
-
* const cfg = new ConfigBuilder()
|
|
14
|
-
* .walletPrivateKey('0x...')
|
|
15
|
-
* .build();
|
|
16
|
-
* ```
|
|
17
|
-
*
|
|
18
|
-
* All fields can also be supplied from environment variables via {@link fromEnv}.
|
|
19
|
-
*/
|
|
20
|
-
class ConfigBuilder {
|
|
21
|
-
_rpcUrl = 'https://ethereum.sepolia.api.4mica.xyz/';
|
|
22
|
-
_walletPrivateKey;
|
|
23
|
-
_signer;
|
|
24
|
-
_ethereumHttpRpcUrl;
|
|
25
|
-
_contractAddress;
|
|
26
|
-
_adminApiKey;
|
|
27
|
-
_bearerToken;
|
|
28
|
-
_authEnabled = true;
|
|
29
|
-
_authUrl;
|
|
30
|
-
_authRefreshMarginSecs;
|
|
31
|
-
/** Set the 4Mica core RPC URL directly. Use {@link network} to select a hosted network by name instead. Defaults to `https://ethereum.sepolia.api.4mica.xyz/`. */
|
|
32
|
-
rpcUrl(value) {
|
|
33
|
-
this._rpcUrl = value;
|
|
34
|
-
return this;
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Select a hosted 4Mica network by shorthand or CAIP-2 identifier.
|
|
38
|
-
* Resolves to the corresponding core API URL.
|
|
39
|
-
* Mutually exclusive with {@link rpcUrl} — last call wins.
|
|
40
|
-
*
|
|
41
|
-
* Supported values: `"base"` / `"eip155:8453"`, `"base-sepolia"` / `"eip155:84532"`,
|
|
42
|
-
* `"ethereum-sepolia"` / `"eip155:11155111"`.
|
|
43
|
-
*
|
|
44
|
-
* @throws {@link ConfigError} if the network is not recognised.
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```ts
|
|
48
|
-
* new ConfigBuilder().network("base").walletPrivateKey("0x...").build();
|
|
49
|
-
* new ConfigBuilder().network("eip155:8453").walletPrivateKey("0x...").build();
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
network(value) {
|
|
53
|
-
const url = (0, networks_1.resolveNetworkRpcUrl)(value);
|
|
54
|
-
if (!url) {
|
|
55
|
-
throw new errors_1.ConfigError(`unknown network "${value}". Use a known shorthand (e.g. "base") or CAIP-2 id, or call rpcUrl() directly.`);
|
|
56
|
-
}
|
|
57
|
-
this._rpcUrl = url;
|
|
58
|
-
return this;
|
|
59
|
-
}
|
|
60
|
-
/** Set the wallet private key (hex string). Mutually exclusive with {@link signer}. */
|
|
61
|
-
walletPrivateKey(value) {
|
|
62
|
-
this._walletPrivateKey = value;
|
|
63
|
-
return this;
|
|
64
|
-
}
|
|
65
|
-
/** Set a pre-built viem `Account` directly. Mutually exclusive with {@link walletPrivateKey}. */
|
|
66
|
-
signer(value) {
|
|
67
|
-
this._signer = value;
|
|
68
|
-
return this;
|
|
69
|
-
}
|
|
70
|
-
/** Override the Ethereum HTTP RPC URL used for on-chain calls. */
|
|
71
|
-
ethereumHttpRpcUrl(value) {
|
|
72
|
-
this._ethereumHttpRpcUrl = value;
|
|
73
|
-
return this;
|
|
74
|
-
}
|
|
75
|
-
/** Override the Core4Mica contract address. */
|
|
76
|
-
contractAddress(value) {
|
|
77
|
-
this._contractAddress = value;
|
|
78
|
-
return this;
|
|
79
|
-
}
|
|
80
|
-
/** Set an admin API key for privileged RPC endpoints. */
|
|
81
|
-
adminApiKey(value) {
|
|
82
|
-
this._adminApiKey = value;
|
|
83
|
-
return this;
|
|
84
|
-
}
|
|
85
|
-
/** Set a static bearer token for authenticated RPC calls. Disables SIWE auth. */
|
|
86
|
-
bearerToken(value) {
|
|
87
|
-
this._bearerToken = value;
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
/** Enable SIWE authentication using the default RPC URL as the auth endpoint. Auth is enabled by default; this is a no-op unless you previously called a method that disabled it. */
|
|
91
|
-
enableAuth() {
|
|
92
|
-
this._authEnabled = true;
|
|
93
|
-
return this;
|
|
94
|
-
}
|
|
95
|
-
/** Set a custom SIWE authentication endpoint and enable auth. */
|
|
96
|
-
authUrl(value) {
|
|
97
|
-
this._authUrl = value;
|
|
98
|
-
this._authEnabled = true;
|
|
99
|
-
return this;
|
|
100
|
-
}
|
|
101
|
-
/** Set the number of seconds before token expiry at which the session proactively refreshes. Enables auth. */
|
|
102
|
-
authRefreshMarginSecs(value) {
|
|
103
|
-
this._authRefreshMarginSecs = value;
|
|
104
|
-
this._authEnabled = true;
|
|
105
|
-
return this;
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Load configuration from environment variables.
|
|
109
|
-
*
|
|
110
|
-
* Recognised variables:
|
|
111
|
-
* - `4MICA_NETWORK` — shorthand or CAIP-2 id (e.g. `base`); takes precedence over `4MICA_RPC_URL`
|
|
112
|
-
* - `4MICA_RPC_URL`
|
|
113
|
-
* - `4MICA_WALLET_PRIVATE_KEY`
|
|
114
|
-
* - `4MICA_ETHEREUM_HTTP_RPC_URL`
|
|
115
|
-
* - `4MICA_CONTRACT_ADDRESS`
|
|
116
|
-
* - `4MICA_ADMIN_API_KEY`
|
|
117
|
-
* - `4MICA_BEARER_TOKEN`
|
|
118
|
-
* - `4MICA_AUTH_URL`
|
|
119
|
-
* - `4MICA_AUTH_REFRESH_MARGIN_SECS`
|
|
120
|
-
*/
|
|
121
|
-
fromEnv() {
|
|
122
|
-
const env = process.env;
|
|
123
|
-
if (env['4MICA_NETWORK'])
|
|
124
|
-
this.network(env['4MICA_NETWORK']);
|
|
125
|
-
else if (env['4MICA_RPC_URL'])
|
|
126
|
-
this._rpcUrl = env['4MICA_RPC_URL'];
|
|
127
|
-
if (env['4MICA_WALLET_PRIVATE_KEY'])
|
|
128
|
-
this._walletPrivateKey = env['4MICA_WALLET_PRIVATE_KEY'];
|
|
129
|
-
if (env['4MICA_ETHEREUM_HTTP_RPC_URL'])
|
|
130
|
-
this._ethereumHttpRpcUrl = env['4MICA_ETHEREUM_HTTP_RPC_URL'];
|
|
131
|
-
if (env['4MICA_CONTRACT_ADDRESS'])
|
|
132
|
-
this._contractAddress = env['4MICA_CONTRACT_ADDRESS'];
|
|
133
|
-
if (env['4MICA_ADMIN_API_KEY'])
|
|
134
|
-
this._adminApiKey = env['4MICA_ADMIN_API_KEY'];
|
|
135
|
-
if (env['4MICA_BEARER_TOKEN'])
|
|
136
|
-
this._bearerToken = env['4MICA_BEARER_TOKEN'];
|
|
137
|
-
if (env['4MICA_AUTH_URL']) {
|
|
138
|
-
this._authUrl = env['4MICA_AUTH_URL'];
|
|
139
|
-
this._authEnabled = true;
|
|
140
|
-
}
|
|
141
|
-
if (env['4MICA_AUTH_REFRESH_MARGIN_SECS']) {
|
|
142
|
-
this._authRefreshMarginSecs = Number(env['4MICA_AUTH_REFRESH_MARGIN_SECS']);
|
|
143
|
-
this._authEnabled = true;
|
|
144
|
-
}
|
|
145
|
-
return this;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Validate all settings and return an immutable {@link Config}.
|
|
149
|
-
*
|
|
150
|
-
* @throws {@link ConfigError} if required fields are missing, URLs are invalid,
|
|
151
|
-
* or the auth refresh margin is not a finite non-negative number.
|
|
152
|
-
*/
|
|
153
|
-
build() {
|
|
154
|
-
if (!this._signer && !this._walletPrivateKey) {
|
|
155
|
-
throw new errors_1.ConfigError('missing signer or wallet_private_key');
|
|
156
|
-
}
|
|
157
|
-
if (!this._rpcUrl) {
|
|
158
|
-
throw new errors_1.ConfigError('missing rpc_url');
|
|
159
|
-
}
|
|
160
|
-
try {
|
|
161
|
-
const rpcUrl = (0, utils_1.validateUrl)(this._rpcUrl);
|
|
162
|
-
const walletPrivateKey = this._walletPrivateKey
|
|
163
|
-
? (0, utils_1.normalizePrivateKey)(this._walletPrivateKey)
|
|
164
|
-
: undefined;
|
|
165
|
-
const signer = this._signer ?? (0, accounts_1.privateKeyToAccount)(walletPrivateKey);
|
|
166
|
-
const ethereumHttpRpcUrl = this._ethereumHttpRpcUrl
|
|
167
|
-
? (0, utils_1.validateUrl)(this._ethereumHttpRpcUrl)
|
|
168
|
-
: undefined;
|
|
169
|
-
const contractAddress = this._contractAddress
|
|
170
|
-
? (0, utils_1.normalizeAddress)(this._contractAddress)
|
|
171
|
-
: undefined;
|
|
172
|
-
const authUrl = this._authUrl ? (0, utils_1.validateUrl)(this._authUrl) : undefined;
|
|
173
|
-
const refreshMargin = this._authRefreshMarginSecs !== undefined ? this._authRefreshMarginSecs : 60;
|
|
174
|
-
if (!Number.isFinite(refreshMargin) || refreshMargin < 0) {
|
|
175
|
-
throw new utils_1.ValidationError('invalid auth refresh margin');
|
|
176
|
-
}
|
|
177
|
-
const authEnabled = this._authEnabled;
|
|
178
|
-
return {
|
|
179
|
-
rpcUrl,
|
|
180
|
-
signer,
|
|
181
|
-
ethereumHttpRpcUrl,
|
|
182
|
-
contractAddress,
|
|
183
|
-
adminApiKey: this._adminApiKey,
|
|
184
|
-
bearerToken: this._bearerToken,
|
|
185
|
-
authUrl: authEnabled ? (authUrl ?? rpcUrl) : undefined,
|
|
186
|
-
authRefreshMarginSecs: authEnabled ? refreshMargin : undefined,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
catch (err) {
|
|
190
|
-
if (err instanceof utils_1.ValidationError) {
|
|
191
|
-
throw new errors_1.ConfigError(err.message);
|
|
192
|
-
}
|
|
193
|
-
throw err;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
exports.ConfigBuilder = ConfigBuilder;
|
package/dist/src/constants.d.ts
DELETED
package/dist/src/constants.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ADMIN_SCOPE_MANAGE_KEYS = exports.ADMIN_SCOPE_SUSPEND_USERS = exports.ADMIN_API_KEY_PREFIX = exports.ADMIN_API_KEY_HEADER = void 0;
|
|
4
|
-
exports.ADMIN_API_KEY_HEADER = 'x-api-key';
|
|
5
|
-
exports.ADMIN_API_KEY_PREFIX = 'ak_';
|
|
6
|
-
exports.ADMIN_SCOPE_SUSPEND_USERS = 'user_suspension:write';
|
|
7
|
-
exports.ADMIN_SCOPE_MANAGE_KEYS = 'admin_api_keys:manage';
|
package/dist/src/contract.d.ts
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import { createPublicClient, createWalletClient, type Hex, type Chain, Account, GetContractReturnType, HttpTransport } from 'viem';
|
|
2
|
-
import { core4micaAbi } from './abi/core4mica';
|
|
3
|
-
type TPublicClient = ReturnType<typeof createPublicClient>;
|
|
4
|
-
type TWalletClient = ReturnType<typeof createWalletClient<HttpTransport, Chain, Account>>;
|
|
5
|
-
type CoreContract = GetContractReturnType<typeof core4micaAbi, {
|
|
6
|
-
public: ReturnType<typeof createPublicClient>;
|
|
7
|
-
wallet: TWalletClient;
|
|
8
|
-
}>;
|
|
9
|
-
export type TxReceiptWaitOptions = {
|
|
10
|
-
timeout?: number;
|
|
11
|
-
pollingInterval?: number;
|
|
12
|
-
gas?: bigint;
|
|
13
|
-
};
|
|
14
|
-
export declare class ContractGateway {
|
|
15
|
-
readonly publicClient: TPublicClient;
|
|
16
|
-
readonly walletClient: TWalletClient;
|
|
17
|
-
readonly contract: CoreContract;
|
|
18
|
-
private erc20Cache;
|
|
19
|
-
private txQueue;
|
|
20
|
-
private constructor();
|
|
21
|
-
static create(rpcUrl: string, signer: Account, contractAddress: Hex, chainId: number): Promise<ContractGateway>;
|
|
22
|
-
private erc20;
|
|
23
|
-
private enqueueTx;
|
|
24
|
-
private defaultFeeParams;
|
|
25
|
-
private splitWaitOptions;
|
|
26
|
-
getGuaranteeDomain(): Promise<string>;
|
|
27
|
-
getGuaranteeVersionConfig(version: number): Promise<{
|
|
28
|
-
domainSeparator: string;
|
|
29
|
-
decoder: string;
|
|
30
|
-
enabled: boolean;
|
|
31
|
-
}>;
|
|
32
|
-
approveErc20(token: string, amount: number | bigint | string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt | undefined>;
|
|
33
|
-
private waitForErc20Allowance;
|
|
34
|
-
deposit(amount: number | bigint | string, erc20Token?: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
35
|
-
getUserAssets(opts?: {
|
|
36
|
-
blockNumber?: bigint;
|
|
37
|
-
}): Promise<{
|
|
38
|
-
asset: `0x${string}`;
|
|
39
|
-
collateral: bigint;
|
|
40
|
-
withdrawalRequestTimestamp: bigint;
|
|
41
|
-
withdrawalRequestAmount: bigint;
|
|
42
|
-
}[]>;
|
|
43
|
-
getPaymentStatus(tabId: number | bigint): Promise<{
|
|
44
|
-
paid: bigint;
|
|
45
|
-
remunerated: boolean;
|
|
46
|
-
asset: Hex;
|
|
47
|
-
}>;
|
|
48
|
-
payTabEth(tabId: number | bigint, reqId: number | bigint, amount: number | bigint | string, recipient: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
49
|
-
payTabErc20(tabId: number | bigint, amount: number | bigint | string, erc20Token: string, recipient: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
50
|
-
requestWithdrawal(amount: number | bigint | string, erc20Token?: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
51
|
-
cancelWithdrawal(erc20Token?: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
52
|
-
finalizeWithdrawal(erc20Token?: string, waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
53
|
-
remunerate(claimsBlob: Uint8Array, signatureWords: Uint8Array[], waitOptions?: TxReceiptWaitOptions): Promise<import("viem").TransactionReceipt>;
|
|
54
|
-
}
|
|
55
|
-
export {};
|
package/dist/src/contract.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ContractGateway = void 0;
|
|
4
|
-
const viem_1 = require("viem");
|
|
5
|
-
const core4mica_1 = require("./abi/core4mica");
|
|
6
|
-
const chain_1 = require("./chain");
|
|
7
|
-
const errors_1 = require("./errors");
|
|
8
|
-
const utils_1 = require("./utils");
|
|
9
|
-
/**
|
|
10
|
-
* Extract a human-readable message from a viem contract error, falling back
|
|
11
|
-
* to the raw message if no structured reason is available.
|
|
12
|
-
*/
|
|
13
|
-
function wrapViemError(error, context) {
|
|
14
|
-
if (error instanceof errors_1.ContractError)
|
|
15
|
-
return error;
|
|
16
|
-
if (error instanceof Error) {
|
|
17
|
-
const e = error;
|
|
18
|
-
const cause = e['cause'];
|
|
19
|
-
const reason = cause?.['reason'] ?? cause?.['message'] ?? e['shortMessage'] ?? error.message;
|
|
20
|
-
const details = e['details'] ?? cause?.['details'];
|
|
21
|
-
const suffix = details ? ` (${details})` : '';
|
|
22
|
-
return new errors_1.ContractError(`${context}: ${reason}${suffix}`);
|
|
23
|
-
}
|
|
24
|
-
return new errors_1.ContractError(`${context}: ${String(error)}`);
|
|
25
|
-
}
|
|
26
|
-
const DEFAULT_REMUNERATE_GAS_LIMIT = 8000000n;
|
|
27
|
-
const DEFAULT_PAY_TAB_ERC20_GAS_LIMIT = 300000n;
|
|
28
|
-
const DEFAULT_MAX_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
|
|
29
|
-
const DEFAULT_MAX_PRIORITY_FEE_PER_GAS = (0, viem_1.parseGwei)('0.1');
|
|
30
|
-
const DEFAULT_RECEIPT_TIMEOUT_MS = 60_000;
|
|
31
|
-
const DEFAULT_RECEIPT_POLLING_INTERVAL_MS = 2_000;
|
|
32
|
-
function sleep(ms) {
|
|
33
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
34
|
-
}
|
|
35
|
-
class ContractGateway {
|
|
36
|
-
publicClient;
|
|
37
|
-
walletClient;
|
|
38
|
-
contract;
|
|
39
|
-
erc20Cache = new Map();
|
|
40
|
-
txQueue = Promise.resolve();
|
|
41
|
-
constructor(publicClient, walletClient, contract) {
|
|
42
|
-
this.publicClient = publicClient;
|
|
43
|
-
this.walletClient = walletClient;
|
|
44
|
-
this.contract = contract;
|
|
45
|
-
}
|
|
46
|
-
static async create(rpcUrl, signer, contractAddress, chainId) {
|
|
47
|
-
const chain = (0, chain_1.getChain)(chainId, rpcUrl);
|
|
48
|
-
const publicClient = (0, viem_1.createPublicClient)({
|
|
49
|
-
transport: (0, viem_1.http)(rpcUrl),
|
|
50
|
-
pollingInterval: 2_000,
|
|
51
|
-
});
|
|
52
|
-
const rpcChainId = await publicClient.getChainId();
|
|
53
|
-
if (rpcChainId !== Number(chainId)) {
|
|
54
|
-
throw new errors_1.ContractError(`Connected to chain ${rpcChainId}, expected ${chainId}`);
|
|
55
|
-
}
|
|
56
|
-
const walletClient = (0, viem_1.createWalletClient)({
|
|
57
|
-
transport: (0, viem_1.http)(rpcUrl),
|
|
58
|
-
account: signer,
|
|
59
|
-
chain,
|
|
60
|
-
});
|
|
61
|
-
const contract = (0, viem_1.getContract)({
|
|
62
|
-
address: contractAddress,
|
|
63
|
-
abi: core4mica_1.core4micaAbi,
|
|
64
|
-
client: {
|
|
65
|
-
public: publicClient,
|
|
66
|
-
wallet: walletClient,
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
return new ContractGateway(publicClient, walletClient, contract);
|
|
70
|
-
}
|
|
71
|
-
erc20(token) {
|
|
72
|
-
if (!this.erc20Cache.has(token)) {
|
|
73
|
-
this.erc20Cache.set(token, (0, viem_1.getContract)({
|
|
74
|
-
address: token,
|
|
75
|
-
abi: viem_1.erc20Abi,
|
|
76
|
-
client: { public: this.publicClient, wallet: this.walletClient },
|
|
77
|
-
}));
|
|
78
|
-
}
|
|
79
|
-
return this.erc20Cache.get(token);
|
|
80
|
-
}
|
|
81
|
-
enqueueTx(fn) {
|
|
82
|
-
// Serialize transaction submissions to avoid nonce collisions.
|
|
83
|
-
const run = this.txQueue.then(fn, fn);
|
|
84
|
-
this.txQueue = run.then(() => undefined, () => undefined);
|
|
85
|
-
return run;
|
|
86
|
-
}
|
|
87
|
-
defaultFeeParams() {
|
|
88
|
-
return {
|
|
89
|
-
maxFeePerGas: DEFAULT_MAX_FEE_PER_GAS,
|
|
90
|
-
maxPriorityFeePerGas: DEFAULT_MAX_PRIORITY_FEE_PER_GAS,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
splitWaitOptions(waitOptions) {
|
|
94
|
-
if (!waitOptions) {
|
|
95
|
-
return { receipt: { timeout: DEFAULT_RECEIPT_TIMEOUT_MS } };
|
|
96
|
-
}
|
|
97
|
-
const { gas, timeout, pollingInterval } = waitOptions;
|
|
98
|
-
return {
|
|
99
|
-
gas,
|
|
100
|
-
receipt: {
|
|
101
|
-
...(timeout !== undefined ? { timeout } : {}),
|
|
102
|
-
...(pollingInterval !== undefined ? { pollingInterval } : {}),
|
|
103
|
-
},
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
async getGuaranteeDomain() {
|
|
107
|
-
return this.contract.read.guaranteeDomainSeparator();
|
|
108
|
-
}
|
|
109
|
-
async getGuaranteeVersionConfig(version) {
|
|
110
|
-
const [, domainSeparator, decoder, enabled] = await this.contract.read.getGuaranteeVersionConfig([BigInt(version)]);
|
|
111
|
-
return { domainSeparator: domainSeparator, decoder: decoder, enabled };
|
|
112
|
-
}
|
|
113
|
-
async approveErc20(token, amount, waitOptions) {
|
|
114
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
115
|
-
const erc20 = this.erc20(token);
|
|
116
|
-
const spender = this.contract.address;
|
|
117
|
-
const targetAllowance = (0, utils_1.parseU256)(amount);
|
|
118
|
-
const account = this.walletClient.account;
|
|
119
|
-
if (account) {
|
|
120
|
-
const currentAllowance = (await erc20.read.allowance([
|
|
121
|
-
account.address,
|
|
122
|
-
spender,
|
|
123
|
-
]));
|
|
124
|
-
if (currentAllowance >= targetAllowance) {
|
|
125
|
-
return undefined;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
const sendApprove = async (value) => {
|
|
129
|
-
const hash = await this.enqueueTx(() => erc20.write.approve([spender, value], this.defaultFeeParams()));
|
|
130
|
-
const txReceipt = await this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
131
|
-
if (txReceipt.status !== 'success') {
|
|
132
|
-
throw new errors_1.ContractError(`approve transaction reverted: ${hash}`);
|
|
133
|
-
}
|
|
134
|
-
return txReceipt;
|
|
135
|
-
};
|
|
136
|
-
let txReceipt;
|
|
137
|
-
try {
|
|
138
|
-
txReceipt = await sendApprove(targetAllowance);
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
// Some ERC20s (e.g. USDT) require resetting allowance to zero before
|
|
142
|
-
// setting a new non-zero value.
|
|
143
|
-
if (targetAllowance === 0n) {
|
|
144
|
-
throw wrapViemError(error, 'ERC20 approve failed');
|
|
145
|
-
}
|
|
146
|
-
try {
|
|
147
|
-
await sendApprove(0n);
|
|
148
|
-
txReceipt = await sendApprove(targetAllowance);
|
|
149
|
-
}
|
|
150
|
-
catch (retryError) {
|
|
151
|
-
throw wrapViemError(retryError, 'ERC20 approve failed after allowance reset');
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (account) {
|
|
155
|
-
const actual = await this.waitForErc20Allowance(erc20, account.address, spender, targetAllowance, receipt);
|
|
156
|
-
if (actual < targetAllowance) {
|
|
157
|
-
throw new errors_1.ContractError(`ERC20 allowance verification failed: on-chain allowance is ${actual} but expected ${targetAllowance}. ` +
|
|
158
|
-
`Try calling approveErc20 again.`);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return txReceipt;
|
|
162
|
-
}
|
|
163
|
-
async waitForErc20Allowance(erc20, owner, spender, targetAllowance, receiptOptions) {
|
|
164
|
-
const timeout = receiptOptions.timeout ?? DEFAULT_RECEIPT_TIMEOUT_MS;
|
|
165
|
-
const pollingInterval = receiptOptions.pollingInterval ?? DEFAULT_RECEIPT_POLLING_INTERVAL_MS;
|
|
166
|
-
const deadline = Date.now() + timeout;
|
|
167
|
-
let actual = 0n;
|
|
168
|
-
while (Date.now() <= deadline) {
|
|
169
|
-
actual = (await erc20.read.allowance([owner, spender]));
|
|
170
|
-
if (actual >= targetAllowance) {
|
|
171
|
-
return actual;
|
|
172
|
-
}
|
|
173
|
-
await sleep(Math.min(pollingInterval, Math.max(0, deadline - Date.now())));
|
|
174
|
-
}
|
|
175
|
-
return actual;
|
|
176
|
-
}
|
|
177
|
-
async deposit(amount, erc20Token, waitOptions) {
|
|
178
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
179
|
-
const parsedAmount = (0, utils_1.parseU256)(amount);
|
|
180
|
-
let hash;
|
|
181
|
-
if (erc20Token) {
|
|
182
|
-
// Pre-check allowance to surface a clear error before hitting the contract.
|
|
183
|
-
const account = this.walletClient.account;
|
|
184
|
-
if (account) {
|
|
185
|
-
const erc20 = this.erc20(erc20Token);
|
|
186
|
-
const allowance = await erc20.read.allowance([
|
|
187
|
-
account.address,
|
|
188
|
-
this.contract.address,
|
|
189
|
-
]);
|
|
190
|
-
if (allowance < parsedAmount) {
|
|
191
|
-
throw new errors_1.ContractError(`Insufficient ERC20 allowance: ${allowance} approved but ${parsedAmount} required. ` +
|
|
192
|
-
`Call approveErc20("${erc20Token}", ${parsedAmount}) before depositing.`);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
try {
|
|
196
|
-
hash = await this.enqueueTx(() => this.contract.write.depositStablecoin([erc20Token, parsedAmount], this.defaultFeeParams()));
|
|
197
|
-
}
|
|
198
|
-
catch (error) {
|
|
199
|
-
throw wrapViemError(error, 'depositStablecoin failed');
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
else {
|
|
203
|
-
try {
|
|
204
|
-
hash = await this.enqueueTx(() => this.contract.write.deposit({ value: parsedAmount, ...this.defaultFeeParams() }));
|
|
205
|
-
}
|
|
206
|
-
catch (error) {
|
|
207
|
-
throw wrapViemError(error, 'deposit failed');
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
211
|
-
}
|
|
212
|
-
async getUserAssets(opts) {
|
|
213
|
-
const account = this.walletClient.account;
|
|
214
|
-
if (!account) {
|
|
215
|
-
throw new errors_1.ContractError('wallet client has no account configured');
|
|
216
|
-
}
|
|
217
|
-
const addr = account.address;
|
|
218
|
-
const result = await this.contract.read.getUserAllAssets([addr], opts);
|
|
219
|
-
return result.map((a) => ({
|
|
220
|
-
asset: a.asset,
|
|
221
|
-
collateral: a.collateral,
|
|
222
|
-
withdrawalRequestTimestamp: a.withdrawalRequestTimestamp,
|
|
223
|
-
withdrawalRequestAmount: a.withdrawalRequestAmount,
|
|
224
|
-
}));
|
|
225
|
-
}
|
|
226
|
-
async getPaymentStatus(tabId) {
|
|
227
|
-
const [paid, remunerated, asset] = await this.contract.read.getPaymentStatus([
|
|
228
|
-
(0, utils_1.parseU256)(tabId),
|
|
229
|
-
]);
|
|
230
|
-
return {
|
|
231
|
-
paid,
|
|
232
|
-
remunerated,
|
|
233
|
-
asset,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
async payTabEth(tabId, reqId, amount, recipient, waitOptions) {
|
|
237
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
238
|
-
const data = new TextEncoder().encode(`tab_id:${tabId.toString(16)};req_id:${reqId.toString(16)}`);
|
|
239
|
-
const hash = await this.enqueueTx(() => this.walletClient.sendTransaction({
|
|
240
|
-
to: recipient,
|
|
241
|
-
value: (0, utils_1.parseU256)(amount),
|
|
242
|
-
data: (0, utils_1.hexFromBytes)(data),
|
|
243
|
-
...this.defaultFeeParams(),
|
|
244
|
-
}));
|
|
245
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
246
|
-
}
|
|
247
|
-
async payTabErc20(tabId, amount, erc20Token, recipient, waitOptions) {
|
|
248
|
-
const { gas, receipt } = this.splitWaitOptions(waitOptions);
|
|
249
|
-
const parsedAmount = (0, utils_1.parseU256)(amount);
|
|
250
|
-
// payTabInERC20Token uses safeTransferFrom, so the contract must be an
|
|
251
|
-
// approved spender. Auto-approve if the current allowance is insufficient.
|
|
252
|
-
await this.approveErc20(erc20Token, parsedAmount, waitOptions);
|
|
253
|
-
const hash = await this.enqueueTx(() => this.contract.write.payTabInERC20Token([(0, utils_1.parseU256)(tabId), erc20Token, parsedAmount, recipient], {
|
|
254
|
-
gas: gas ?? DEFAULT_PAY_TAB_ERC20_GAS_LIMIT,
|
|
255
|
-
...this.defaultFeeParams(),
|
|
256
|
-
}));
|
|
257
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
258
|
-
}
|
|
259
|
-
async requestWithdrawal(amount, erc20Token, waitOptions) {
|
|
260
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
261
|
-
const value = (0, utils_1.parseU256)(amount);
|
|
262
|
-
let hash;
|
|
263
|
-
if (erc20Token) {
|
|
264
|
-
hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([erc20Token, value], this.defaultFeeParams()));
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
hash = await this.enqueueTx(() => this.contract.write.requestWithdrawal([value], this.defaultFeeParams()));
|
|
268
|
-
}
|
|
269
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
270
|
-
}
|
|
271
|
-
async cancelWithdrawal(erc20Token, waitOptions) {
|
|
272
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
273
|
-
let hash;
|
|
274
|
-
if (erc20Token) {
|
|
275
|
-
hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal([erc20Token], this.defaultFeeParams()));
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
hash = await this.enqueueTx(() => this.contract.write.cancelWithdrawal(this.defaultFeeParams()));
|
|
279
|
-
}
|
|
280
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
281
|
-
}
|
|
282
|
-
async finalizeWithdrawal(erc20Token, waitOptions) {
|
|
283
|
-
const { receipt } = this.splitWaitOptions(waitOptions);
|
|
284
|
-
let hash;
|
|
285
|
-
if (erc20Token) {
|
|
286
|
-
hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal([erc20Token], this.defaultFeeParams()));
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
hash = await this.enqueueTx(() => this.contract.write.finalizeWithdrawal(this.defaultFeeParams()));
|
|
290
|
-
}
|
|
291
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
292
|
-
}
|
|
293
|
-
async remunerate(claimsBlob, signatureWords, waitOptions) {
|
|
294
|
-
const { gas, receipt } = this.splitWaitOptions(waitOptions);
|
|
295
|
-
const sigStruct = {
|
|
296
|
-
x_c0_a: (0, utils_1.hexFromBytes)(signatureWords[0]),
|
|
297
|
-
x_c0_b: (0, utils_1.hexFromBytes)(signatureWords[1]),
|
|
298
|
-
x_c1_a: (0, utils_1.hexFromBytes)(signatureWords[2]),
|
|
299
|
-
x_c1_b: (0, utils_1.hexFromBytes)(signatureWords[3]),
|
|
300
|
-
y_c0_a: (0, utils_1.hexFromBytes)(signatureWords[4]),
|
|
301
|
-
y_c0_b: (0, utils_1.hexFromBytes)(signatureWords[5]),
|
|
302
|
-
y_c1_a: (0, utils_1.hexFromBytes)(signatureWords[6]),
|
|
303
|
-
y_c1_b: (0, utils_1.hexFromBytes)(signatureWords[7]),
|
|
304
|
-
};
|
|
305
|
-
const hash = await this.enqueueTx(() => this.contract.write.remunerate([(0, utils_1.hexFromBytes)(claimsBlob), sigStruct], {
|
|
306
|
-
gas: gas ?? DEFAULT_REMUNERATE_GAS_LIMIT,
|
|
307
|
-
...this.defaultFeeParams(),
|
|
308
|
-
}));
|
|
309
|
-
return this.publicClient.waitForTransactionReceipt({ hash, ...receipt });
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
exports.ContractGateway = ContractGateway;
|
package/dist/src/debug.d.ts
DELETED
package/dist/src/debug.js
DELETED
package/dist/src/errors.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/** Base class for all 4Mica SDK errors. Sets `error.name` to the subclass name. */
|
|
2
|
-
export declare class FourMicaError extends Error {
|
|
3
|
-
constructor(message: string);
|
|
4
|
-
}
|
|
5
|
-
/** Thrown when the SDK configuration is invalid (e.g. missing required fields or bad URL). */
|
|
6
|
-
export declare class ConfigError extends FourMicaError {
|
|
7
|
-
}
|
|
8
|
-
/** Thrown when a 4Mica core RPC call fails. Includes the HTTP status and raw response body. */
|
|
9
|
-
export declare class RpcError extends FourMicaError {
|
|
10
|
-
readonly status?: number;
|
|
11
|
-
readonly body?: unknown;
|
|
12
|
-
constructor(message: string, options?: {
|
|
13
|
-
status?: number;
|
|
14
|
-
body?: unknown;
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
/** Thrown when the SDK client fails to initialise (e.g. chain ID mismatch). */
|
|
18
|
-
export declare class ClientInitializationError extends FourMicaError {
|
|
19
|
-
}
|
|
20
|
-
/** Thrown when signing a payment claim fails (e.g. unsupported scheme, address mismatch). */
|
|
21
|
-
export declare class SigningError extends FourMicaError {
|
|
22
|
-
}
|
|
23
|
-
/** Thrown when an on-chain contract call fails or returns an unexpected result. */
|
|
24
|
-
export declare class ContractError extends FourMicaError {
|
|
25
|
-
}
|
|
26
|
-
/** Thrown when BLS certificate verification fails (e.g. domain mismatch, invalid encoding). */
|
|
27
|
-
export declare class VerificationError extends FourMicaError {
|
|
28
|
-
}
|
|
29
|
-
/** Thrown when an x402 HTTP payment flow encounters an error. */
|
|
30
|
-
export declare class X402Error extends FourMicaError {
|
|
31
|
-
}
|
|
32
|
-
/** Base class for authentication-related errors. */
|
|
33
|
-
export declare class AuthError extends FourMicaError {
|
|
34
|
-
}
|
|
35
|
-
/** Thrown when the auth URL is invalid or unreachable. */
|
|
36
|
-
export declare class AuthUrlError extends AuthError {
|
|
37
|
-
}
|
|
38
|
-
/** Thrown when a network-level error occurs during authentication. */
|
|
39
|
-
export declare class AuthTransportError extends AuthError {
|
|
40
|
-
}
|
|
41
|
-
/** Thrown when the auth server response cannot be decoded. */
|
|
42
|
-
export declare class AuthDecodeError extends AuthError {
|
|
43
|
-
}
|
|
44
|
-
/** Thrown when the auth server returns an error response. Includes HTTP status and body. */
|
|
45
|
-
export declare class AuthApiError extends AuthError {
|
|
46
|
-
readonly status?: number;
|
|
47
|
-
readonly body?: unknown;
|
|
48
|
-
constructor(message: string, options?: {
|
|
49
|
-
status?: number;
|
|
50
|
-
body?: unknown;
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
/** Thrown when auth configuration is invalid. */
|
|
54
|
-
export declare class AuthConfigError extends AuthError {
|
|
55
|
-
}
|
|
56
|
-
/** Thrown when an authenticated operation is attempted without auth being configured. */
|
|
57
|
-
export declare class AuthMissingConfigError extends AuthConfigError {
|
|
58
|
-
}
|