@4mica/sdk 0.5.4 → 0.5.6

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/dist/models.js CHANGED
@@ -1,16 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RecipientPaymentInfo = exports.AssetBalanceInfo = exports.CollateralEventInfo = exports.PendingRemunerationInfo = exports.GuaranteeInfo = exports.TabInfo = exports.AdminApiKeySecret = exports.AdminApiKeyInfo = exports.UserSuspensionStatus = exports.PaymentGuaranteeRequestClaims = exports.ADMIN_SCOPE_MANAGE_KEYS = exports.ADMIN_SCOPE_SUSPEND_USERS = exports.ADMIN_API_KEY_PREFIX = exports.ADMIN_API_KEY_HEADER = exports.SigningScheme = void 0;
3
+ exports.RecipientPaymentInfo = exports.AssetBalanceInfo = exports.CollateralEventInfo = exports.PendingRemunerationInfo = exports.GuaranteeInfo = exports.TabInfo = exports.AdminApiKeySecret = exports.AdminApiKeyInfo = exports.UserSuspensionStatus = exports.PaymentGuaranteeRequestClaims = exports.SigningScheme = exports.ADMIN_SCOPE_SUSPEND_USERS = exports.ADMIN_SCOPE_MANAGE_KEYS = exports.ADMIN_API_KEY_PREFIX = exports.ADMIN_API_KEY_HEADER = void 0;
4
+ const serde_1 = require("./serde");
4
5
  const utils_1 = require("./utils");
6
+ var constants_1 = require("./constants");
7
+ Object.defineProperty(exports, "ADMIN_API_KEY_HEADER", { enumerable: true, get: function () { return constants_1.ADMIN_API_KEY_HEADER; } });
8
+ Object.defineProperty(exports, "ADMIN_API_KEY_PREFIX", { enumerable: true, get: function () { return constants_1.ADMIN_API_KEY_PREFIX; } });
9
+ Object.defineProperty(exports, "ADMIN_SCOPE_MANAGE_KEYS", { enumerable: true, get: function () { return constants_1.ADMIN_SCOPE_MANAGE_KEYS; } });
10
+ Object.defineProperty(exports, "ADMIN_SCOPE_SUSPEND_USERS", { enumerable: true, get: function () { return constants_1.ADMIN_SCOPE_SUSPEND_USERS; } });
5
11
  var SigningScheme;
6
12
  (function (SigningScheme) {
7
13
  SigningScheme["EIP712"] = "eip712";
8
14
  SigningScheme["EIP191"] = "eip191";
9
15
  })(SigningScheme || (exports.SigningScheme = SigningScheme = {}));
10
- exports.ADMIN_API_KEY_HEADER = 'x-api-key';
11
- exports.ADMIN_API_KEY_PREFIX = 'ak_';
12
- exports.ADMIN_SCOPE_SUSPEND_USERS = 'user_suspension:write';
13
- exports.ADMIN_SCOPE_MANAGE_KEYS = 'admin_api_keys:manage';
14
16
  class PaymentGuaranteeRequestClaims {
15
17
  userAddress;
16
18
  recipientAddress;
@@ -52,7 +54,7 @@ class UserSuspensionStatus {
52
54
  this.updatedAt = updatedAt;
53
55
  }
54
56
  static fromRpc(raw) {
55
- return new UserSuspensionStatus((getAny(raw, 'user_address', 'userAddress') ?? ''), Boolean(getAny(raw, 'suspended')), Number(getAny(raw, 'updated_at', 'updatedAt') ?? 0));
57
+ return new UserSuspensionStatus(((0, serde_1.getAny)(raw, 'user_address', 'userAddress') ?? ''), Boolean((0, serde_1.getAny)(raw, 'suspended')), Number((0, serde_1.getAny)(raw, 'updated_at', 'updatedAt') ?? 0));
56
58
  }
57
59
  }
58
60
  exports.UserSuspensionStatus = UserSuspensionStatus;
@@ -70,8 +72,8 @@ class AdminApiKeyInfo {
70
72
  this.revokedAt = revokedAt;
71
73
  }
72
74
  static fromRpc(raw) {
73
- const revoked = getAny(raw, 'revoked_at', 'revokedAt');
74
- return new AdminApiKeyInfo((getAny(raw, 'id') ?? ''), (getAny(raw, 'name') ?? ''), (getAny(raw, 'scopes') ?? []).map(String), Number(getAny(raw, 'created_at', 'createdAt') ?? 0), revoked === undefined || revoked === null ? null : Number(revoked));
75
+ const revoked = (0, serde_1.getAny)(raw, 'revoked_at', 'revokedAt');
76
+ return new AdminApiKeyInfo(((0, serde_1.getAny)(raw, 'id') ?? ''), ((0, serde_1.getAny)(raw, 'name') ?? ''), ((0, serde_1.getAny)(raw, 'scopes') ?? []).map(String), Number((0, serde_1.getAny)(raw, 'created_at', 'createdAt') ?? 0), revoked === undefined || revoked === null ? null : Number(revoked));
75
77
  }
76
78
  }
77
79
  exports.AdminApiKeyInfo = AdminApiKeyInfo;
@@ -89,17 +91,10 @@ class AdminApiKeySecret {
89
91
  this.apiKey = apiKey;
90
92
  }
91
93
  static fromRpc(raw) {
92
- return new AdminApiKeySecret((getAny(raw, 'id') ?? ''), (getAny(raw, 'name') ?? ''), (getAny(raw, 'scopes') ?? []).map(String), Number(getAny(raw, 'created_at', 'createdAt') ?? 0), (getAny(raw, 'api_key', 'apiKey') ?? ''));
94
+ return new AdminApiKeySecret(((0, serde_1.getAny)(raw, 'id') ?? ''), ((0, serde_1.getAny)(raw, 'name') ?? ''), ((0, serde_1.getAny)(raw, 'scopes') ?? []).map(String), Number((0, serde_1.getAny)(raw, 'created_at', 'createdAt') ?? 0), ((0, serde_1.getAny)(raw, 'api_key', 'apiKey') ?? ''));
93
95
  }
94
96
  }
95
97
  exports.AdminApiKeySecret = AdminApiKeySecret;
96
- function getAny(raw, ...keys) {
97
- for (const key of keys) {
98
- if (key in raw)
99
- return raw[key];
100
- }
101
- return undefined;
102
- }
103
98
  class TabInfo {
104
99
  tabId;
105
100
  userAddress;
@@ -124,7 +119,7 @@ class TabInfo {
124
119
  this.updatedAt = updatedAt;
125
120
  }
126
121
  static fromRpc(raw) {
127
- return new TabInfo((0, utils_1.parseU256)((getAny(raw, 'tab_id', 'tabId') ?? 0)), (getAny(raw, 'user_address', 'userAddress') ?? ''), (getAny(raw, 'recipient_address', 'recipientAddress') ?? ''), (getAny(raw, 'asset_address', 'assetAddress') ?? ''), Number(getAny(raw, 'start_timestamp', 'startTimestamp')), Number(getAny(raw, 'ttl_seconds', 'ttlSeconds')), (getAny(raw, 'status') ?? ''), (getAny(raw, 'settlement_status', 'settlementStatus') ?? ''), Number(getAny(raw, 'created_at', 'createdAt')), Number(getAny(raw, 'updated_at', 'updatedAt')));
122
+ return new TabInfo((0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'tab_id', 'tabId') ?? 0)), ((0, serde_1.getAny)(raw, 'user_address', 'userAddress') ?? ''), ((0, serde_1.getAny)(raw, 'recipient_address', 'recipientAddress') ?? ''), ((0, serde_1.getAny)(raw, 'asset_address', 'assetAddress') ?? ''), Number((0, serde_1.getAny)(raw, 'start_timestamp', 'startTimestamp')), Number((0, serde_1.getAny)(raw, 'ttl_seconds', 'ttlSeconds')), ((0, serde_1.getAny)(raw, 'status') ?? ''), ((0, serde_1.getAny)(raw, 'settlement_status', 'settlementStatus') ?? ''), Number((0, serde_1.getAny)(raw, 'created_at', 'createdAt')), Number((0, serde_1.getAny)(raw, 'updated_at', 'updatedAt')));
128
123
  }
129
124
  }
130
125
  exports.TabInfo = TabInfo;
@@ -148,7 +143,7 @@ class GuaranteeInfo {
148
143
  this.certificate = certificate;
149
144
  }
150
145
  static fromRpc(raw) {
151
- return new GuaranteeInfo((0, utils_1.parseU256)((getAny(raw, 'tab_id', 'tabId') ?? 0)), (0, utils_1.parseU256)((getAny(raw, 'req_id', 'reqId') ?? 0)), (getAny(raw, 'from_address', 'fromAddress') ?? ''), (getAny(raw, 'to_address', 'toAddress') ?? ''), (getAny(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)((getAny(raw, 'amount') ?? 0)), Number(getAny(raw, 'start_timestamp', 'startTimestamp', 'timestamp') ?? 0), getAny(raw, 'certificate'));
146
+ return new GuaranteeInfo((0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'tab_id', 'tabId') ?? 0)), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'req_id', 'reqId') ?? 0)), ((0, serde_1.getAny)(raw, 'from_address', 'fromAddress') ?? ''), ((0, serde_1.getAny)(raw, 'to_address', 'toAddress') ?? ''), ((0, serde_1.getAny)(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'amount') ?? 0)), Number((0, serde_1.getAny)(raw, 'start_timestamp', 'startTimestamp', 'timestamp') ?? 0), (0, serde_1.getAny)(raw, 'certificate'));
152
147
  }
153
148
  }
154
149
  exports.GuaranteeInfo = GuaranteeInfo;
@@ -160,8 +155,8 @@ class PendingRemunerationInfo {
160
155
  this.latestGuarantee = latestGuarantee;
161
156
  }
162
157
  static fromRpc(raw) {
163
- const latest = getAny(raw, 'latest_guarantee', 'latestGuarantee');
164
- return new PendingRemunerationInfo(TabInfo.fromRpc(getAny(raw, 'tab') ?? {}), latest ? GuaranteeInfo.fromRpc(latest) : null);
158
+ const latest = (0, serde_1.getAny)(raw, 'latest_guarantee', 'latestGuarantee');
159
+ return new PendingRemunerationInfo(TabInfo.fromRpc((0, serde_1.getAny)(raw, 'tab') ?? {}), latest ? GuaranteeInfo.fromRpc(latest) : null);
165
160
  }
166
161
  }
167
162
  exports.PendingRemunerationInfo = PendingRemunerationInfo;
@@ -187,9 +182,9 @@ class CollateralEventInfo {
187
182
  this.createdAt = createdAt;
188
183
  }
189
184
  static fromRpc(raw) {
190
- const tabId = getAny(raw, 'tab_id', 'tabId');
191
- const reqId = getAny(raw, 'req_id', 'reqId');
192
- return new CollateralEventInfo((getAny(raw, 'id') ?? ''), (getAny(raw, 'user_address', 'userAddress') ?? ''), (getAny(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)((getAny(raw, 'amount') ?? 0)), (getAny(raw, 'event_type', 'eventType') ?? ''), tabId !== undefined && tabId !== null ? (0, utils_1.parseU256)(tabId) : null, reqId !== undefined && reqId !== null ? (0, utils_1.parseU256)(reqId) : null, getAny(raw, 'tx_id', 'txId'), Number(getAny(raw, 'created_at', 'createdAt') ?? 0));
185
+ const tabId = (0, serde_1.getAny)(raw, 'tab_id', 'tabId');
186
+ const reqId = (0, serde_1.getAny)(raw, 'req_id', 'reqId');
187
+ return new CollateralEventInfo(((0, serde_1.getAny)(raw, 'id') ?? ''), ((0, serde_1.getAny)(raw, 'user_address', 'userAddress') ?? ''), ((0, serde_1.getAny)(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'amount') ?? 0)), ((0, serde_1.getAny)(raw, 'event_type', 'eventType') ?? ''), tabId !== undefined && tabId !== null ? (0, utils_1.parseU256)(tabId) : null, reqId !== undefined && reqId !== null ? (0, utils_1.parseU256)(reqId) : null, (0, serde_1.getAny)(raw, 'tx_id', 'txId'), Number((0, serde_1.getAny)(raw, 'created_at', 'createdAt') ?? 0));
193
188
  }
194
189
  }
195
190
  exports.CollateralEventInfo = CollateralEventInfo;
@@ -209,7 +204,7 @@ class AssetBalanceInfo {
209
204
  this.updatedAt = updatedAt;
210
205
  }
211
206
  static fromRpc(raw) {
212
- return new AssetBalanceInfo((getAny(raw, 'user_address', 'userAddress') ?? ''), (getAny(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)((getAny(raw, 'total') ?? 0)), (0, utils_1.parseU256)((getAny(raw, 'locked') ?? 0)), Number(getAny(raw, 'version') ?? 0), Number(getAny(raw, 'updated_at', 'updatedAt') ?? 0));
207
+ return new AssetBalanceInfo(((0, serde_1.getAny)(raw, 'user_address', 'userAddress') ?? ''), ((0, serde_1.getAny)(raw, 'asset_address', 'assetAddress') ?? ''), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'total') ?? 0)), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'locked') ?? 0)), Number((0, serde_1.getAny)(raw, 'version') ?? 0), Number((0, serde_1.getAny)(raw, 'updated_at', 'updatedAt') ?? 0));
213
208
  }
214
209
  }
215
210
  exports.AssetBalanceInfo = AssetBalanceInfo;
@@ -233,7 +228,7 @@ class RecipientPaymentInfo {
233
228
  this.createdAt = createdAt;
234
229
  }
235
230
  static fromRpc(raw) {
236
- return new RecipientPaymentInfo((getAny(raw, 'user_address', 'userAddress') ?? ''), (getAny(raw, 'recipient_address', 'recipientAddress') ?? ''), (getAny(raw, 'tx_hash', 'txHash') ?? ''), (0, utils_1.parseU256)((getAny(raw, 'amount') ?? 0)), Boolean(getAny(raw, 'verified')), Boolean(getAny(raw, 'finalized')), Boolean(getAny(raw, 'failed')), Number(getAny(raw, 'created_at', 'createdAt') ?? 0));
231
+ return new RecipientPaymentInfo(((0, serde_1.getAny)(raw, 'user_address', 'userAddress') ?? ''), ((0, serde_1.getAny)(raw, 'recipient_address', 'recipientAddress') ?? ''), ((0, serde_1.getAny)(raw, 'tx_hash', 'txHash') ?? ''), (0, utils_1.parseU256)(((0, serde_1.getAny)(raw, 'amount') ?? 0)), Boolean((0, serde_1.getAny)(raw, 'verified')), Boolean((0, serde_1.getAny)(raw, 'finalized')), Boolean((0, serde_1.getAny)(raw, 'failed')), Number((0, serde_1.getAny)(raw, 'created_at', 'createdAt') ?? 0));
237
232
  }
238
233
  }
239
234
  exports.RecipientPaymentInfo = RecipientPaymentInfo;
@@ -0,0 +1,19 @@
1
+ import { PaymentGuaranteeRequestClaims, PaymentSignature, SigningScheme } from './models';
2
+ export interface PaymentPayloadClaims {
3
+ version: string;
4
+ user_address: string;
5
+ recipient_address: string;
6
+ tab_id: string;
7
+ req_id: string;
8
+ amount: string;
9
+ timestamp: number;
10
+ asset_address: string;
11
+ }
12
+ export interface PaymentPayload {
13
+ claims: PaymentPayloadClaims;
14
+ signature: string;
15
+ scheme: SigningScheme;
16
+ }
17
+ export declare function serializePaymentClaims(claims: PaymentGuaranteeRequestClaims): PaymentPayloadClaims;
18
+ export declare function buildPaymentPayload(claims: PaymentGuaranteeRequestClaims, signature: PaymentSignature): PaymentPayload;
19
+ export declare function buildPaymentPayload(claims: PaymentGuaranteeRequestClaims, signature: string, scheme: SigningScheme): PaymentPayload;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.serializePaymentClaims = serializePaymentClaims;
4
+ exports.buildPaymentPayload = buildPaymentPayload;
5
+ const utils_1 = require("./utils");
6
+ function serializePaymentClaims(claims) {
7
+ return {
8
+ version: 'v1',
9
+ user_address: claims.userAddress,
10
+ recipient_address: claims.recipientAddress,
11
+ tab_id: (0, utils_1.serializeU256)(claims.tabId),
12
+ req_id: (0, utils_1.serializeU256)(claims.reqId),
13
+ amount: (0, utils_1.serializeU256)(claims.amount),
14
+ asset_address: claims.assetAddress,
15
+ timestamp: claims.timestamp,
16
+ };
17
+ }
18
+ function buildPaymentPayload(claims, signature, scheme) {
19
+ const signed = typeof signature === 'string'
20
+ ? (() => {
21
+ if (!scheme) {
22
+ throw new Error('scheme is required when providing a signature string');
23
+ }
24
+ return { signature, scheme };
25
+ })()
26
+ : signature;
27
+ return {
28
+ claims: serializePaymentClaims(claims),
29
+ signature: signed.signature,
30
+ scheme: signed.scheme,
31
+ };
32
+ }
package/dist/rpc.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AdminApiKeyInfo, AdminApiKeySecret, UserSuspensionStatus } from './models';
2
2
  import { CorePublicParameters } from './signing';
3
- export type FetchFn = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
3
+ import { type FetchFn as HttpFetchFn } from './http';
4
+ export type FetchFn = HttpFetchFn;
4
5
  export type BearerTokenProvider = () => string | Promise<string>;
5
6
  export declare class RpcProxy {
6
7
  private baseUrl;
@@ -14,12 +15,11 @@ export declare class RpcProxy {
14
15
  withTokenProvider(provider: BearerTokenProvider): RpcProxy;
15
16
  private headers;
16
17
  private resolveBearerToken;
17
- private decode;
18
18
  private get;
19
19
  private post;
20
20
  getPublicParams(): Promise<CorePublicParameters>;
21
- issueGuarantee(body: Record<string, unknown>): Promise<Record<string, unknown>>;
22
- createPaymentTab(body: Record<string, unknown>): Promise<Record<string, unknown>>;
21
+ issueGuarantee(body: unknown): Promise<Record<string, unknown>>;
22
+ createPaymentTab(body: unknown): Promise<Record<string, unknown>>;
23
23
  listSettledTabs(recipientAddress: string): Promise<Record<string, unknown>[]>;
24
24
  listPendingRemunerations(recipientAddress: string): Promise<Record<string, unknown>[]>;
25
25
  getTab(tabId: number | bigint): Promise<Record<string, unknown> | null>;
@@ -31,7 +31,7 @@ export declare class RpcProxy {
31
31
  getCollateralEventsForTab(tabId: number | bigint): Promise<Record<string, unknown>[]>;
32
32
  getUserAssetBalance(userAddress: string, assetAddress: string): Promise<Record<string, unknown> | null>;
33
33
  updateUserSuspension(userAddress: string, suspended: boolean): Promise<UserSuspensionStatus>;
34
- createAdminApiKey(body: Record<string, unknown>): Promise<AdminApiKeySecret>;
34
+ createAdminApiKey(body: unknown): Promise<AdminApiKeySecret>;
35
35
  listAdminApiKeys(): Promise<AdminApiKeyInfo[]>;
36
36
  revokeAdminApiKey(keyId: string): Promise<AdminApiKeyInfo>;
37
37
  }
package/dist/rpc.js CHANGED
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RpcProxy = void 0;
4
+ const constants_1 = require("./constants");
4
5
  const models_1 = require("./models");
5
6
  const signing_1 = require("./signing");
6
7
  const errors_1 = require("./errors");
8
+ const http_1 = require("./http");
7
9
  function serializeTabId(tabId) {
8
10
  return `0x${BigInt(tabId).toString(16)}`;
9
11
  }
@@ -14,7 +16,7 @@ class RpcProxy {
14
16
  bearerTokenProvider;
15
17
  fetchFn;
16
18
  constructor(endpoint, adminApiKey, fetchFn = fetch) {
17
- this.baseUrl = endpoint.endsWith('/') ? endpoint.slice(0, -1) : endpoint;
19
+ this.baseUrl = (0, http_1.normalizeBaseUrl)(endpoint);
18
20
  this.adminApiKey = adminApiKey;
19
21
  this.fetchFn = fetchFn;
20
22
  }
@@ -32,7 +34,7 @@ class RpcProxy {
32
34
  async headers() {
33
35
  const headers = {};
34
36
  if (this.adminApiKey) {
35
- headers[models_1.ADMIN_API_KEY_HEADER] = this.adminApiKey;
37
+ headers[constants_1.ADMIN_API_KEY_HEADER] = this.adminApiKey;
36
38
  }
37
39
  const token = await this.resolveBearerToken();
38
40
  if (token) {
@@ -54,52 +56,30 @@ class RpcProxy {
54
56
  }
55
57
  return `Bearer ${trimmed}`;
56
58
  }
57
- async decode(response) {
58
- let payload;
59
- try {
60
- payload = await response.json();
61
- }
62
- catch (err) {
63
- if (response.ok) {
64
- throw new errors_1.RpcError(`invalid JSON response from ${response.url}: ${String(err)}`);
65
- }
66
- payload = await response.text();
67
- }
68
- if (response.ok) {
69
- return payload;
70
- }
71
- let message = 'unknown error';
72
- if (payload && typeof payload === 'object') {
73
- const record = payload;
74
- const error = record.error;
75
- const msg = record.message;
76
- message =
77
- (typeof error === 'string' && error) ||
78
- (typeof msg === 'string' && msg) ||
79
- JSON.stringify(record, (_k, v) => v);
80
- }
81
- else if (typeof payload === 'string' && payload.trim()) {
82
- message = payload.trim();
83
- }
84
- throw new errors_1.RpcError(`${response.status}: ${message}`, {
85
- status: response.status,
86
- body: payload,
87
- });
88
- }
89
59
  async get(path) {
90
- const resp = await this.fetchFn(`${this.baseUrl}${path}`, {
60
+ return (0, http_1.requestJson)(this.fetchFn, `${this.baseUrl}${path}`, {
91
61
  headers: await this.headers(),
92
62
  method: 'GET',
63
+ }, {
64
+ decodeError: (message) => new errors_1.RpcError(message),
65
+ httpError: (message, response, body) => new errors_1.RpcError(message, {
66
+ status: response.status,
67
+ body,
68
+ }),
93
69
  });
94
- return this.decode(resp);
95
70
  }
96
71
  async post(path, body) {
97
- const resp = await this.fetchFn(`${this.baseUrl}${path}`, {
72
+ return (0, http_1.requestJson)(this.fetchFn, `${this.baseUrl}${path}`, {
98
73
  headers: { 'content-type': 'application/json', ...(await this.headers()) },
99
74
  method: 'POST',
100
75
  body: JSON.stringify(body),
76
+ }, {
77
+ decodeError: (message) => new errors_1.RpcError(message),
78
+ httpError: (message, response, body) => new errors_1.RpcError(message, {
79
+ status: response.status,
80
+ body,
81
+ }),
101
82
  });
102
- return this.decode(resp);
103
83
  }
104
84
  async getPublicParams() {
105
85
  const data = await this.get('/core/public-params');
@@ -0,0 +1,5 @@
1
+ export type RecordValue = Record<string, unknown>;
2
+ export declare const isRecord: (value: unknown) => value is RecordValue;
3
+ export declare function getAny<T>(raw: RecordValue, ...keys: string[]): T | undefined;
4
+ export declare function readString(value: unknown, label: string, onError: (label: string) => Error): string;
5
+ export declare function readNumber(value: unknown, label: string, onError: (label: string) => Error): number;
package/dist/serde.js ADDED
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isRecord = void 0;
4
+ exports.getAny = getAny;
5
+ exports.readString = readString;
6
+ exports.readNumber = readNumber;
7
+ const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
8
+ exports.isRecord = isRecord;
9
+ function getAny(raw, ...keys) {
10
+ for (const key of keys) {
11
+ if (key in raw)
12
+ return raw[key];
13
+ }
14
+ return undefined;
15
+ }
16
+ function readString(value, label, onError) {
17
+ if (typeof value === 'string' && value.trim()) {
18
+ return value;
19
+ }
20
+ throw onError(label);
21
+ }
22
+ function readNumber(value, label, onError) {
23
+ if (typeof value === 'number' && Number.isFinite(value)) {
24
+ return value;
25
+ }
26
+ if (typeof value === 'string' && value.trim()) {
27
+ const parsed = Number(value);
28
+ if (Number.isFinite(parsed)) {
29
+ return parsed;
30
+ }
31
+ }
32
+ throw onError(label);
33
+ }
package/dist/signing.js CHANGED
@@ -9,6 +9,7 @@ const viem_1 = require("viem");
9
9
  const errors_1 = require("./errors");
10
10
  const models_1 = require("./models");
11
11
  const utils_1 = require("./utils");
12
+ const serde_1 = require("./serde");
12
13
  class CorePublicParameters {
13
14
  publicKey;
14
15
  contractAddress;
@@ -53,7 +54,6 @@ exports.GUARANTEE_EIP712_TYPES = {
53
54
  { name: 'timestamp', type: 'uint64' },
54
55
  ],
55
56
  };
56
- const isRecord = (value) => Boolean(value) && typeof value === 'object' && !Array.isArray(value);
57
57
  const fieldsMatch = (actual, expected) => {
58
58
  if (!Array.isArray(actual) || actual.length !== expected.length)
59
59
  return false;
@@ -79,16 +79,16 @@ const ensureBigIntish = (value, label) => {
79
79
  }
80
80
  };
81
81
  function validateGuaranteeTypedData(payload, options = {}) {
82
- if (!isRecord(payload)) {
82
+ if (!(0, serde_1.isRecord)(payload)) {
83
83
  throw new utils_1.ValidationError('typed data payload is required');
84
84
  }
85
- if (!isRecord(payload.domain)) {
85
+ if (!(0, serde_1.isRecord)(payload.domain)) {
86
86
  throw new utils_1.ValidationError('domain is required');
87
87
  }
88
- if (!isRecord(payload.types)) {
88
+ if (!(0, serde_1.isRecord)(payload.types)) {
89
89
  throw new utils_1.ValidationError('types are required');
90
90
  }
91
- if (!isRecord(payload.message)) {
91
+ if (!(0, serde_1.isRecord)(payload.message)) {
92
92
  throw new utils_1.ValidationError('message is required');
93
93
  }
94
94
  const types = payload.types;
@@ -18,5 +18,5 @@ export declare class X402Flow {
18
18
  protected requestTab(x402Version: number, paymentRequirements: PaymentRequirementsV1 | PaymentRequirementsV2, userAddress: string, resource?: X402ResourceInfo): Promise<TabResponse>;
19
19
  protected buildClaims(requirements: PaymentRequirementsV1 | PaymentRequirementsV2, tab: TabResponse, userAddress: string): PaymentGuaranteeRequestClaims;
20
20
  private static validateScheme;
21
- private static buildPaymentPayload;
21
+ private static decodePaymentHeader;
22
22
  }
@@ -18,6 +18,7 @@ exports.X402Flow = void 0;
18
18
  const models_1 = require("../models");
19
19
  const utils_1 = require("../utils");
20
20
  const errors_1 = require("../errors");
21
+ const payment_1 = require("../payment");
21
22
  __exportStar(require("./models"), exports);
22
23
  class X402Flow {
23
24
  signer;
@@ -34,7 +35,7 @@ class X402Flow {
34
35
  const tab = await this.requestTab(1, paymentRequirements, userAddress);
35
36
  const claims = this.buildClaims(paymentRequirements, tab, userAddress);
36
37
  const signature = await this.signer.signPayment(claims, models_1.SigningScheme.EIP712);
37
- const paymentPayload = X402Flow.buildPaymentPayload(claims, signature);
38
+ const paymentPayload = (0, payment_1.buildPaymentPayload)(claims, signature);
38
39
  const envelope = {
39
40
  x402Version: 1,
40
41
  scheme: paymentRequirements.scheme,
@@ -49,7 +50,7 @@ class X402Flow {
49
50
  const tab = await this.requestTab(2, accepted, userAddress, paymentRequired.resource);
50
51
  const claims = this.buildClaims(accepted, tab, userAddress);
51
52
  const signature = await this.signer.signPayment(claims, models_1.SigningScheme.EIP712);
52
- const paymentPayload = X402Flow.buildPaymentPayload(claims, signature);
53
+ const paymentPayload = (0, payment_1.buildPaymentPayload)(claims, signature);
53
54
  const envelope = {
54
55
  x402Version: 2,
55
56
  accepted: accepted,
@@ -61,12 +62,17 @@ class X402Flow {
61
62
  }
62
63
  async settlePayment(payment, paymentRequirements, facilitatorUrl) {
63
64
  const url = `${facilitatorUrl.replace(/\/$/, '')}/settle`;
65
+ const paymentPayload = X402Flow.decodePaymentHeader(payment.header);
66
+ const x402Version = typeof paymentPayload === 'object' && paymentPayload && 'x402Version' in paymentPayload
67
+ ? paymentPayload.x402Version
68
+ : undefined;
64
69
  const response = await this.fetchFn(url, {
65
70
  method: 'POST',
66
71
  headers: { 'content-type': 'application/json' },
67
72
  body: JSON.stringify({
68
- x402Version: 1,
73
+ ...(x402Version ? { x402Version } : {}),
69
74
  paymentHeader: payment.header,
75
+ paymentPayload,
70
76
  paymentRequirements,
71
77
  }),
72
78
  });
@@ -118,21 +124,17 @@ class X402Flow {
118
124
  throw new errors_1.X402Error(`invalid scheme: ${scheme}`);
119
125
  }
120
126
  }
121
- static buildPaymentPayload(claims, signature) {
122
- return {
123
- claims: {
124
- version: 'v1',
125
- user_address: claims.userAddress,
126
- recipient_address: claims.recipientAddress,
127
- tab_id: `0x${claims.tabId.toString(16)}`,
128
- req_id: `0x${claims.reqId.toString(16)}`,
129
- amount: `0x${claims.amount.toString(16)}`,
130
- asset_address: claims.assetAddress,
131
- timestamp: claims.timestamp,
132
- },
133
- signature: signature.signature,
134
- scheme: signature.scheme,
135
- };
127
+ static decodePaymentHeader(header) {
128
+ if (!header || typeof header !== 'string') {
129
+ throw new errors_1.X402Error('missing payment header');
130
+ }
131
+ try {
132
+ const decoded = Buffer.from(header, 'base64').toString('utf8');
133
+ return JSON.parse(decoded);
134
+ }
135
+ catch (err) {
136
+ throw new errors_1.X402Error(`invalid payment header: ${String(err)}`);
137
+ }
136
138
  }
137
139
  }
138
140
  exports.X402Flow = X402Flow;
@@ -1,4 +1,5 @@
1
- import { PaymentSignature, SigningScheme } from '../models';
1
+ import { PaymentSignature } from '../models';
2
+ import type { PaymentPayload, PaymentPayloadClaims } from '../payment';
2
3
  export interface PaymentRequirementsV1 {
3
4
  scheme: string;
4
5
  network: string;
@@ -30,21 +31,8 @@ export interface TabResponse {
30
31
  userAddress: string;
31
32
  nextReqId?: string;
32
33
  }
33
- export interface X402PaymentPayloadClaims {
34
- version: string;
35
- user_address: string;
36
- recipient_address: string;
37
- tab_id: string;
38
- req_id: string;
39
- amount: string;
40
- timestamp: number;
41
- asset_address: string;
42
- }
43
- export interface X402PaymentPayload {
44
- claims: X402PaymentPayloadClaims;
45
- signature: string;
46
- scheme: SigningScheme;
47
- }
34
+ export type X402PaymentPayloadClaims = PaymentPayloadClaims;
35
+ export type X402PaymentPayload = PaymentPayload;
48
36
  export interface X402PaymentEnvelopeV1 {
49
37
  x402Version: number;
50
38
  scheme: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4mica/sdk",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "TypeScript SDK for interacting with the 4Mica payment network",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -45,6 +45,7 @@
45
45
  "fmt": "prettier --check \"{src,tests}/**/*.{ts,js,json}\""
46
46
  },
47
47
  "dependencies": {
48
+ "@noble/curves": "^2.0.1",
48
49
  "viem": "^2.45.1"
49
50
  },
50
51
  "devDependencies": {
@@ -57,6 +58,7 @@
57
58
  "eslint-plugin-react": "^7.37.5",
58
59
  "globals": "^17.3.0",
59
60
  "prettier": "^3.8.1",
61
+ "tsx": "^4.21.0",
60
62
  "typescript": "^5.3.3",
61
63
  "typescript-eslint": "^8.54.0",
62
64
  "vitest": "^4.0.17"