@veridex/sdk 1.1.5 → 1.1.7
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/{EVMClient-Bmy9czkE.d.mts → EVMClient-DqDiFak8.d.mts} +1 -1
- package/dist/auth/prepareAuth.d.mts +5 -4
- package/dist/auth/prepareAuth.js +143 -1422
- package/dist/auth/prepareAuth.js.map +1 -1
- package/dist/auth/prepareAuth.mjs +17 -96
- package/dist/auth/prepareAuth.mjs.map +1 -1
- package/dist/chains/aptos/index.d.mts +1 -1
- package/dist/chains/aptos/index.js +11 -33
- package/dist/chains/aptos/index.js.map +1 -1
- package/dist/chains/aptos/index.mjs +2 -2
- package/dist/chains/avalanche/index.d.mts +2 -2
- package/dist/chains/avalanche/index.js +19 -115
- package/dist/chains/avalanche/index.js.map +1 -1
- package/dist/chains/avalanche/index.mjs +3 -3
- package/dist/chains/evm/index.d.mts +5 -4
- package/dist/chains/evm/index.js +19 -115
- package/dist/chains/evm/index.js.map +1 -1
- package/dist/chains/evm/index.mjs +2 -2
- package/dist/chains/solana/index.d.mts +1 -1
- package/dist/chains/solana/index.js +11 -33
- package/dist/chains/solana/index.js.map +1 -1
- package/dist/chains/solana/index.mjs +2 -2
- package/dist/chains/stacks/index.d.mts +1 -1
- package/dist/chains/stacks/index.js +11 -38
- package/dist/chains/stacks/index.js.map +1 -1
- package/dist/chains/stacks/index.mjs +2 -2
- package/dist/chains/starknet/index.d.mts +36 -2
- package/dist/chains/starknet/index.js +208 -37
- package/dist/chains/starknet/index.js.map +1 -1
- package/dist/chains/starknet/index.mjs +9 -4
- package/dist/chains/stellar/index.d.mts +2 -1
- package/dist/chains/sui/index.d.mts +1 -1
- package/dist/chains/sui/index.js +11 -27
- package/dist/chains/sui/index.js.map +1 -1
- package/dist/chains/sui/index.mjs +2 -2
- package/dist/{chunk-ZNIVNPGF.mjs → chunk-3PCAVZUZ.mjs} +173 -37
- package/dist/chunk-3PCAVZUZ.mjs.map +1 -0
- package/dist/{chunk-DQOW3G7M.mjs → chunk-6BINP4RT.mjs} +48 -9
- package/dist/{chunk-DQOW3G7M.mjs.map → chunk-6BINP4RT.mjs.map} +1 -1
- package/dist/{chunk-7KN6Y4GX.mjs → chunk-AK5HWYX4.mjs} +12 -40
- package/dist/chunk-AK5HWYX4.mjs.map +1 -0
- package/dist/{chunk-QVTADARB.mjs → chunk-FPSCAGYS.mjs} +12 -35
- package/dist/chunk-FPSCAGYS.mjs.map +1 -0
- package/dist/{chunk-USVZH4QC.mjs → chunk-H3WRT6Y4.mjs} +20 -117
- package/dist/chunk-H3WRT6Y4.mjs.map +1 -0
- package/dist/{chunk-GXJUY2SC.mjs → chunk-MNH22BM2.mjs} +12 -35
- package/dist/chunk-MNH22BM2.mjs.map +1 -0
- package/dist/chunk-N42LPFPJ.mjs +177 -0
- package/dist/chunk-N42LPFPJ.mjs.map +1 -0
- package/dist/{chunk-D57UJ4L5.mjs → chunk-NKSRF45N.mjs} +12 -29
- package/dist/chunk-NKSRF45N.mjs.map +1 -0
- package/dist/{chunk-BJH5HJL5.mjs → chunk-SKZLZFE2.mjs} +91 -65
- package/dist/chunk-SKZLZFE2.mjs.map +1 -0
- package/dist/{chunk-NVRAQPSF.mjs → chunk-UF5NWMSQ.mjs} +20 -4
- package/dist/chunk-UF5NWMSQ.mjs.map +1 -0
- package/dist/chunk-WC4X3MAO.mjs +58 -0
- package/dist/chunk-WC4X3MAO.mjs.map +1 -0
- package/dist/{chunk-5FH67KLG.mjs → chunk-XHDOSV2F.mjs} +2 -2
- package/dist/{index-CKKUV4J7.d.mts → index-D1nb2JV9.d.mts} +2 -2
- package/dist/index-qyOqd8tx.d.mts +517 -0
- package/dist/index.d.mts +30 -366
- package/dist/index.js +2412 -2486
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +986 -55
- package/dist/index.mjs.map +1 -1
- package/dist/passkey-fh8bo2w-.d.mts +241 -0
- package/dist/passkey.d.mts +2 -182
- package/dist/passkey.js +86 -7
- package/dist/passkey.js.map +1 -1
- package/dist/passkey.mjs +2 -1
- package/dist/payload.d.mts +22 -28
- package/dist/payload.js +50 -9
- package/dist/payload.js.map +1 -1
- package/dist/payload.mjs +7 -3
- package/dist/platform/index.d.mts +3 -0
- package/dist/platform/index.js +216 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/index.mjs +21 -0
- package/dist/platform/index.mjs.map +1 -0
- package/dist/{portfolio-W2FQ2G3O.mjs → portfolio-MLP2JIFK.mjs} +2 -3
- package/dist/queries/index.mjs +324 -10
- package/dist/queries/index.mjs.map +1 -1
- package/dist/{types-DP2CQT8p.d.mts → types-CdlEbixV.d.mts} +12 -1
- package/dist/types.d.mts +1 -0
- package/dist/types.js.map +1 -1
- package/package.json +7 -1
- package/dist/chunk-72ZA3OYQ.mjs +0 -20
- package/dist/chunk-72ZA3OYQ.mjs.map +0 -1
- package/dist/chunk-7KN6Y4GX.mjs.map +0 -1
- package/dist/chunk-BJH5HJL5.mjs.map +0 -1
- package/dist/chunk-D57UJ4L5.mjs.map +0 -1
- package/dist/chunk-GXJUY2SC.mjs.map +0 -1
- package/dist/chunk-NVRAQPSF.mjs.map +0 -1
- package/dist/chunk-QVTADARB.mjs.map +0 -1
- package/dist/chunk-USVZH4QC.mjs.map +0 -1
- package/dist/chunk-XDIIFIW6.mjs +0 -330
- package/dist/chunk-XDIIFIW6.mjs.map +0 -1
- package/dist/chunk-ZNIVNPGF.mjs.map +0 -1
- package/dist/chunk-ZXMTPBSP.mjs +0 -857
- package/dist/chunk-ZXMTPBSP.mjs.map +0 -1
- /package/dist/{chunk-5FH67KLG.mjs.map → chunk-XHDOSV2F.mjs.map} +0 -0
- /package/dist/{portfolio-W2FQ2G3O.mjs.map → portfolio-MLP2JIFK.mjs.map} +0 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
// src/platform/PlatformClient.ts
|
|
2
|
+
var PlatformClient = class {
|
|
3
|
+
tenantId;
|
|
4
|
+
appId;
|
|
5
|
+
environment;
|
|
6
|
+
executionBaseUrl;
|
|
7
|
+
controlPlaneBaseUrl;
|
|
8
|
+
apiKey;
|
|
9
|
+
controlPlaneToken;
|
|
10
|
+
timeoutMs;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.executionBaseUrl = trim(config.executionBaseUrl);
|
|
13
|
+
this.controlPlaneBaseUrl = config.controlPlaneBaseUrl ? trim(config.controlPlaneBaseUrl) : void 0;
|
|
14
|
+
this.apiKey = config.apiKey;
|
|
15
|
+
this.controlPlaneToken = config.controlPlaneToken;
|
|
16
|
+
this.tenantId = config.tenantId;
|
|
17
|
+
this.appId = config.appId;
|
|
18
|
+
this.environment = config.environment;
|
|
19
|
+
this.timeoutMs = config.timeoutMs ?? 15e3;
|
|
20
|
+
}
|
|
21
|
+
quote(action, idempotencyKey) {
|
|
22
|
+
return this.execution("/execution/quotes", {
|
|
23
|
+
method: "POST",
|
|
24
|
+
body: action,
|
|
25
|
+
idempotencyKey
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async reserve(quote, executionId, idempotencyKey, chargeAuthorization) {
|
|
29
|
+
this.assertQuoteScope(quote);
|
|
30
|
+
return await this.execution("/execution/reservations", {
|
|
31
|
+
method: "POST",
|
|
32
|
+
body: { quote, executionId, chargeAuthorization },
|
|
33
|
+
idempotencyKey
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
submitSponsored(action, executionId) {
|
|
37
|
+
return this.execution("/submit", {
|
|
38
|
+
method: "POST",
|
|
39
|
+
body: action,
|
|
40
|
+
extraHeaders: { "X-Execution-Id": executionId }
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
getExecution(executionId) {
|
|
44
|
+
return this.execution(`/executions/${encodeURIComponent(executionId)}`);
|
|
45
|
+
}
|
|
46
|
+
listExecutionAttempts(executionId) {
|
|
47
|
+
return this.execution(`/executions/${encodeURIComponent(executionId)}/attempts`);
|
|
48
|
+
}
|
|
49
|
+
cancelExecution(executionId, reason) {
|
|
50
|
+
return this.execution(`/executions/${encodeURIComponent(executionId)}/cancel`, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
body: { reason }
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
listExecutions(limit = 50) {
|
|
56
|
+
return this.execution(
|
|
57
|
+
`/apps/${encodeURIComponent(this.appId)}/executions?environment=${this.environment}&limit=${limit}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
listReconciliationIssues() {
|
|
61
|
+
return this.execution(
|
|
62
|
+
`/apps/${encodeURIComponent(this.appId)}/reconciliation-issues?environment=${this.environment}`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
listChainCapabilities() {
|
|
66
|
+
return this.execution(
|
|
67
|
+
`/apps/${encodeURIComponent(this.appId)}/chain-capabilities?environment=${this.environment}`
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
getSponsorshipPolicy() {
|
|
71
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/sponsorship-policy`);
|
|
72
|
+
}
|
|
73
|
+
putSponsorshipPolicy(policy) {
|
|
74
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/sponsorship-policy`, {
|
|
75
|
+
method: "PUT",
|
|
76
|
+
body: policy
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
listGateways() {
|
|
80
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways`);
|
|
81
|
+
}
|
|
82
|
+
createGateway(config) {
|
|
83
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways`, {
|
|
84
|
+
method: "POST",
|
|
85
|
+
body: config
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
updateGateway(gatewayId, config) {
|
|
89
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways/${encodeURIComponent(gatewayId)}`, {
|
|
90
|
+
method: "PUT",
|
|
91
|
+
body: config
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
listFinancialSummary() {
|
|
95
|
+
return this.execution(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/financial-summary`);
|
|
96
|
+
}
|
|
97
|
+
fund(amount, asset, idempotencyKey) {
|
|
98
|
+
return this.execution(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/funding`, {
|
|
99
|
+
method: "POST",
|
|
100
|
+
body: { amount, asset, idempotencyKey }
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
refund(transactionId, reason, idempotencyKey) {
|
|
104
|
+
return this.execution(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/refunds`, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
body: { transactionId, reason, idempotencyKey }
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
listPayments() {
|
|
110
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/payments`);
|
|
111
|
+
}
|
|
112
|
+
listCharges() {
|
|
113
|
+
return this.execution(`/apps/${encodeURIComponent(this.appId)}/sponsorship/charges`);
|
|
114
|
+
}
|
|
115
|
+
listInvoices() {
|
|
116
|
+
return this.execution(`/apps/${encodeURIComponent(this.appId)}/invoices`);
|
|
117
|
+
}
|
|
118
|
+
listBazaarResources(query = "") {
|
|
119
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/bazaar?q=${encodeURIComponent(query)}`);
|
|
120
|
+
}
|
|
121
|
+
publishResource(resourceId) {
|
|
122
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/resources/${encodeURIComponent(resourceId)}/publish`, { method: "POST" });
|
|
123
|
+
}
|
|
124
|
+
createChargeAuthorization(authorization) {
|
|
125
|
+
if (authorization.tenantId !== this.tenantId || authorization.appId !== this.appId || authorization.environment !== this.environment) {
|
|
126
|
+
throw new Error("CHARGE_AUTHORIZATION_SCOPE_MISMATCH");
|
|
127
|
+
}
|
|
128
|
+
return this.controlPlane(`/v1/apps/${encodeURIComponent(this.appId)}/charge-authorizations`, {
|
|
129
|
+
method: "POST",
|
|
130
|
+
body: authorization
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
assertQuoteScope(quote) {
|
|
134
|
+
if (quote.tenantId !== this.tenantId || quote.appId !== this.appId || quote.environment !== this.environment) {
|
|
135
|
+
throw new Error("SPONSORSHIP_QUOTE_SCOPE_MISMATCH");
|
|
136
|
+
}
|
|
137
|
+
if (Date.parse(quote.expiresAt) <= Date.now()) throw new Error("SPONSORSHIP_QUOTE_EXPIRED");
|
|
138
|
+
}
|
|
139
|
+
execution(path, options = {}) {
|
|
140
|
+
return request(`${this.executionBaseUrl}${path}`, this.timeoutMs, {
|
|
141
|
+
"X-API-Key": this.apiKey,
|
|
142
|
+
"X-Tenant-Id": this.tenantId,
|
|
143
|
+
...options.extraHeaders
|
|
144
|
+
}, options);
|
|
145
|
+
}
|
|
146
|
+
controlPlane(path, options = {}) {
|
|
147
|
+
if (!this.controlPlaneBaseUrl || !this.controlPlaneToken) throw new Error("CONTROL_PLANE_NOT_CONFIGURED");
|
|
148
|
+
return request(`${this.controlPlaneBaseUrl}${path}`, this.timeoutMs, {
|
|
149
|
+
Authorization: `Bearer ${this.controlPlaneToken}`,
|
|
150
|
+
"X-Veridex-Tenant-Id": this.tenantId
|
|
151
|
+
}, options);
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
async function request(url, timeoutMs, baseHeaders, options) {
|
|
155
|
+
const response = await fetch(url, {
|
|
156
|
+
method: options.method ?? "GET",
|
|
157
|
+
headers: {
|
|
158
|
+
Accept: "application/json",
|
|
159
|
+
...baseHeaders,
|
|
160
|
+
...options.body !== void 0 ? { "Content-Type": "application/json" } : {},
|
|
161
|
+
...options.idempotencyKey ? { "Idempotency-Key": options.idempotencyKey } : {}
|
|
162
|
+
},
|
|
163
|
+
...options.body !== void 0 ? { body: JSON.stringify(options.body) } : {},
|
|
164
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
165
|
+
});
|
|
166
|
+
const body = await response.json().catch(() => ({}));
|
|
167
|
+
if (!response.ok) throw new Error(body.error ?? `Platform request failed (${response.status})`);
|
|
168
|
+
return body;
|
|
169
|
+
}
|
|
170
|
+
function trim(value) {
|
|
171
|
+
return value.replace(/\/+$/, "");
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export {
|
|
175
|
+
PlatformClient
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=chunk-N42LPFPJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/platform/PlatformClient.ts"],"sourcesContent":["import type {\n ChargeAuthorization,\n ExecutionAttempt,\n ExecutionRecord,\n GatewayConfigData,\n GatewayConfigResource,\n PlatformClientConfig,\n ReconciliationIssue,\n SponsorshipQuote,\n} from './types.js';\nimport type { SubmitSignedActionRequest } from '../core/RelayerClient.js';\n\nexport class PlatformClient {\n readonly tenantId: string;\n readonly appId: string;\n readonly environment: 'test' | 'live';\n private readonly executionBaseUrl: string;\n private readonly controlPlaneBaseUrl?: string;\n private readonly apiKey: string;\n private readonly controlPlaneToken?: string;\n private readonly timeoutMs: number;\n\n constructor(config: PlatformClientConfig) {\n this.executionBaseUrl = trim(config.executionBaseUrl);\n this.controlPlaneBaseUrl = config.controlPlaneBaseUrl ? trim(config.controlPlaneBaseUrl) : undefined;\n this.apiKey = config.apiKey;\n this.controlPlaneToken = config.controlPlaneToken;\n this.tenantId = config.tenantId;\n this.appId = config.appId;\n this.environment = config.environment;\n this.timeoutMs = config.timeoutMs ?? 15_000;\n }\n\n quote(action: SubmitSignedActionRequest, idempotencyKey: string) {\n return this.execution<{ quote: SponsorshipQuote; simulation: Record<string, string | number> }>('/execution/quotes', {\n method: 'POST', body: action, idempotencyKey,\n });\n }\n\n async reserve(quote: SponsorshipQuote, executionId: string, idempotencyKey: string, chargeAuthorization?: ChargeAuthorization) {\n this.assertQuoteScope(quote);\n return await this.execution<{ executionId: string; reservations: unknown[] }>('/execution/reservations', {\n method: 'POST', body: { quote, executionId, chargeAuthorization }, idempotencyKey,\n });\n }\n\n submitSponsored(action: SubmitSignedActionRequest, executionId: string) {\n return this.execution<{ success: boolean; transactionHash?: string; sequence?: string; actualSponsoredCost?: string }>('/submit', {\n method: 'POST', body: action, extraHeaders: { 'X-Execution-Id': executionId },\n });\n }\n\n getExecution(executionId: string) {\n return this.execution<{ execution: ExecutionRecord }>(`/executions/${encodeURIComponent(executionId)}`);\n }\n\n listExecutionAttempts(executionId: string) {\n return this.execution<{ attempts: ExecutionAttempt[] }>(`/executions/${encodeURIComponent(executionId)}/attempts`);\n }\n\n cancelExecution(executionId: string, reason?: string) {\n return this.execution<{ execution: ExecutionRecord }>(`/executions/${encodeURIComponent(executionId)}/cancel`, {\n method: 'POST', body: { reason },\n });\n }\n\n listExecutions(limit = 50) {\n return this.execution<{ executions: unknown[] }>(\n `/apps/${encodeURIComponent(this.appId)}/executions?environment=${this.environment}&limit=${limit}`,\n );\n }\n\n listReconciliationIssues() {\n return this.execution<{ issues: ReconciliationIssue[] }>(\n `/apps/${encodeURIComponent(this.appId)}/reconciliation-issues?environment=${this.environment}`,\n );\n }\n\n listChainCapabilities() {\n return this.execution<{ capabilities: unknown[] }>(\n `/apps/${encodeURIComponent(this.appId)}/chain-capabilities?environment=${this.environment}`,\n );\n }\n\n getSponsorshipPolicy() {\n return this.controlPlane<Record<string, unknown>>(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/sponsorship-policy`);\n }\n\n putSponsorshipPolicy(policy: Record<string, unknown>) {\n return this.controlPlane<Record<string, unknown>>(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/sponsorship-policy`, {\n method: 'PUT', body: policy,\n });\n }\n\n listGateways() {\n return this.controlPlane<GatewayConfigResource[]>(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways`);\n }\n\n createGateway(config: Omit<GatewayConfigData, 'appId' | 'environment' | 'updatedBy'>) {\n return this.controlPlane<GatewayConfigResource>(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways`, {\n method: 'POST', body: config,\n });\n }\n\n updateGateway(gatewayId: string, config: Omit<GatewayConfigData, 'appId' | 'environment' | 'updatedBy'>) {\n return this.controlPlane<GatewayConfigResource>(`/v1/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/gateways/${encodeURIComponent(gatewayId)}`, {\n method: 'PUT', body: config,\n });\n }\n\n listFinancialSummary() {\n return this.execution<Record<string, unknown>>(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/financial-summary`);\n }\n\n fund(amount: string, asset: string, idempotencyKey: string) {\n return this.execution<Record<string, unknown>>(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/funding`, {\n method: 'POST', body: { amount, asset, idempotencyKey },\n });\n }\n\n refund(transactionId: string, reason: string, idempotencyKey: string) {\n return this.execution<Record<string, unknown>>(`/apps/${encodeURIComponent(this.appId)}/environments/${this.environment}/refunds`, {\n method: 'POST', body: { transactionId, reason, idempotencyKey },\n });\n }\n\n listPayments() { return this.controlPlane<{ payments: unknown[] }>(`/v1/apps/${encodeURIComponent(this.appId)}/payments`); }\n listCharges() { return this.execution<{ charges: unknown[] }>(`/apps/${encodeURIComponent(this.appId)}/sponsorship/charges`); }\n listInvoices() { return this.execution<{ invoices: unknown[] }>(`/apps/${encodeURIComponent(this.appId)}/invoices`); }\n listBazaarResources(query = '') { return this.controlPlane<{ resources: unknown[] }>(`/v1/apps/${encodeURIComponent(this.appId)}/bazaar?q=${encodeURIComponent(query)}`); }\n publishResource(resourceId: string) { return this.controlPlane<Record<string, unknown>>(`/v1/apps/${encodeURIComponent(this.appId)}/resources/${encodeURIComponent(resourceId)}/publish`, { method: 'POST' }); }\n\n createChargeAuthorization(authorization: ChargeAuthorization) {\n if (authorization.tenantId !== this.tenantId || authorization.appId !== this.appId || authorization.environment !== this.environment) {\n throw new Error('CHARGE_AUTHORIZATION_SCOPE_MISMATCH');\n }\n return this.controlPlane<Record<string, unknown>>(`/v1/apps/${encodeURIComponent(this.appId)}/charge-authorizations`, {\n method: 'POST', body: authorization,\n });\n }\n\n private assertQuoteScope(quote: SponsorshipQuote) {\n if (quote.tenantId !== this.tenantId || quote.appId !== this.appId || quote.environment !== this.environment) {\n throw new Error('SPONSORSHIP_QUOTE_SCOPE_MISMATCH');\n }\n if (Date.parse(quote.expiresAt) <= Date.now()) throw new Error('SPONSORSHIP_QUOTE_EXPIRED');\n }\n\n private execution<T>(path: string, options: RequestOptions = {}) {\n return request<T>(`${this.executionBaseUrl}${path}`, this.timeoutMs, {\n 'X-API-Key': this.apiKey,\n 'X-Tenant-Id': this.tenantId,\n ...options.extraHeaders,\n }, options);\n }\n\n private controlPlane<T>(path: string, options: RequestOptions = {}) {\n if (!this.controlPlaneBaseUrl || !this.controlPlaneToken) throw new Error('CONTROL_PLANE_NOT_CONFIGURED');\n return request<T>(`${this.controlPlaneBaseUrl}${path}`, this.timeoutMs, {\n Authorization: `Bearer ${this.controlPlaneToken}`,\n 'X-Veridex-Tenant-Id': this.tenantId,\n }, options);\n }\n}\n\ninterface RequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n idempotencyKey?: string;\n extraHeaders?: Record<string, string>;\n}\n\nasync function request<T>(url: string, timeoutMs: number, baseHeaders: Record<string, string>, options: RequestOptions): Promise<T> {\n const response = await fetch(url, {\n method: options.method ?? 'GET',\n headers: {\n Accept: 'application/json',\n ...baseHeaders,\n ...(options.body !== undefined ? { 'Content-Type': 'application/json' } : {}),\n ...(options.idempotencyKey ? { 'Idempotency-Key': options.idempotencyKey } : {}),\n },\n ...(options.body !== undefined ? { body: JSON.stringify(options.body) } : {}),\n signal: AbortSignal.timeout(timeoutMs),\n });\n const body = await response.json().catch(() => ({}));\n if (!response.ok) throw new Error((body as { error?: string }).error ?? `Platform request failed (${response.status})`);\n return body as T;\n}\n\nfunction trim(value: string): string { return value.replace(/\\/+$/, ''); }\n"],"mappings":"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","names":[]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
encodeBridgeAction,
|
|
3
3
|
encodeExecuteAction,
|
|
4
4
|
encodeTransferAction
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-6BINP4RT.mjs";
|
|
6
6
|
|
|
7
7
|
// src/chains/sui/SuiClient.ts
|
|
8
8
|
import { SuiClient as MystenSuiClient } from "@mysten/sui/client";
|
|
@@ -63,33 +63,16 @@ var SuiClient = class {
|
|
|
63
63
|
);
|
|
64
64
|
}
|
|
65
65
|
async dispatchGasless(signature, publicKeyX, publicKeyY, targetChain, actionPayload, nonce, relayerUrl) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
nonce: Number(nonce)
|
|
77
|
-
};
|
|
78
|
-
const response = await fetch(`${relayerUrl}/api/v1/submit`, {
|
|
79
|
-
method: "POST",
|
|
80
|
-
headers: { "Content-Type": "application/json" },
|
|
81
|
-
body: JSON.stringify(request)
|
|
82
|
-
});
|
|
83
|
-
if (!response.ok) {
|
|
84
|
-
throw new Error(`Relayer submission failed: ${response.status} ${response.statusText}`);
|
|
85
|
-
}
|
|
86
|
-
const result = await response.json();
|
|
87
|
-
return {
|
|
88
|
-
transactionHash: result.transactionHash ?? result.txHash,
|
|
89
|
-
sequence: BigInt(result.sequence || 0),
|
|
90
|
-
userKeyHash: keyHash,
|
|
91
|
-
targetChain
|
|
92
|
-
};
|
|
66
|
+
void signature;
|
|
67
|
+
void publicKeyX;
|
|
68
|
+
void publicKeyY;
|
|
69
|
+
void targetChain;
|
|
70
|
+
void actionPayload;
|
|
71
|
+
void nonce;
|
|
72
|
+
void relayerUrl;
|
|
73
|
+
throw new Error(
|
|
74
|
+
"ChainClient.dispatchGasless() cannot bind v3 destination metadata. Use VeridexSDK.transferViaRelayer() or bridgeViaRelayer()."
|
|
75
|
+
);
|
|
93
76
|
}
|
|
94
77
|
async getVaultAddress(userKeyHash) {
|
|
95
78
|
return this.computeVaultAddress(userKeyHash);
|
|
@@ -461,4 +444,4 @@ var SuiClient = class {
|
|
|
461
444
|
export {
|
|
462
445
|
SuiClient
|
|
463
446
|
};
|
|
464
|
-
//# sourceMappingURL=chunk-
|
|
447
|
+
//# sourceMappingURL=chunk-NKSRF45N.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/chains/sui/SuiClient.ts"],"sourcesContent":["/**\n * Veridex Protocol SDK - Sui Chain Client\n *\n * Production-grade implementation of ChainClient interface for Sui.\n * Supports session management, query-based execution, and vault operations.\n *\n * Security:\n * - Native sui::ecdsa_k1::secp256k1_verify for signature validation\n * - CCQ-based session validation with 60s staleness window\n * - Replay protection via nonce verification\n *\n * Note: Sui is a spoke chain. Session registration/revocation happens on Hub.\n */\n\nimport { SuiClient as MystenSuiClient } from '@mysten/sui/client';\nimport { createHash } from 'crypto';\nimport type { SessionKey } from '../../sessions/types.js';\nimport type {\n ChainClient,\n ChainConfig,\n TransferParams,\n ExecuteParams,\n BridgeParams,\n DispatchResult,\n WebAuthnSignature,\n VaultCreationResult,\n RegisterSessionParams,\n RevokeSessionParams,\n SessionValidationResult,\n} from '../../core/types.js';\nimport { encodeTransferAction, encodeExecuteAction, encodeBridgeAction } from '../../payload.js';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface SuiClientConfig {\n wormholeChainId: number;\n rpcUrl: string;\n packageId: string; // Veridex Spoke package ID\n wormholeCoreBridge: string;\n tokenBridge?: string;\n network?: 'mainnet' | 'testnet' | 'devnet';\n hubRpcUrl?: string; // Hub chain RPC for session management\n hubContractAddress?: string; // Hub contract for session management\n}\n\n// ============================================================================\n// SuiClient\n// ============================================================================\n\nexport class SuiClient implements ChainClient {\n private config: ChainConfig;\n private client: MystenSuiClient;\n private packageId: string;\n private hubRpcUrl?: string;\n private hubContractAddress?: string;\n\n constructor(config: SuiClientConfig) {\n this.config = {\n name: `Sui ${config.network || 'mainnet'}`,\n chainId: 0,\n wormholeChainId: config.wormholeChainId,\n rpcUrl: config.rpcUrl,\n explorerUrl: config.network === 'testnet'\n ? 'https://suiscan.xyz/testnet'\n : config.network === 'devnet'\n ? 'https://suiscan.xyz/devnet'\n : 'https://suiscan.xyz/mainnet',\n isEvm: false,\n contracts: {\n hub: config.packageId,\n wormholeCoreBridge: config.wormholeCoreBridge,\n tokenBridge: config.tokenBridge,\n },\n };\n\n this.client = new MystenSuiClient({ url: config.rpcUrl });\n this.packageId = config.packageId;\n this.hubRpcUrl = config.hubRpcUrl;\n this.hubContractAddress = config.hubContractAddress;\n }\n\n getConfig(): ChainConfig {\n return this.config;\n }\n\n async getNonce(_userKeyHash: string): Promise<bigint> {\n // Nonce is managed on the Hub for cross-chain actions.\n return 0n;\n }\n\n async getMessageFee(): Promise<bigint> {\n // Wormhole fees for Sui are generally handled by relayer submission.\n return 0n;\n }\n\n async buildTransferPayload(params: TransferParams): Promise<string> {\n return encodeTransferAction(params.token, params.recipient, params.amount);\n }\n\n async buildExecutePayload(params: ExecuteParams): Promise<string> {\n return encodeExecuteAction(params.target, params.value, params.data);\n }\n\n async buildBridgePayload(params: BridgeParams): Promise<string> {\n return encodeBridgeAction(params.token, params.amount, params.destinationChain, params.recipient);\n }\n\n async dispatch(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n signer: any\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void signer;\n throw new Error(\n 'Direct dispatch not supported on Sui spoke chains. ' +\n 'Actions must be dispatched from the Hub (EVM) chain. '\n );\n }\n\n async dispatchGasless(\n signature: WebAuthnSignature,\n publicKeyX: bigint,\n publicKeyY: bigint,\n targetChain: number,\n actionPayload: string,\n nonce: bigint,\n relayerUrl: string\n ): Promise<DispatchResult> {\n void signature;\n void publicKeyX;\n void publicKeyY;\n void targetChain;\n void actionPayload;\n void nonce;\n void relayerUrl;\n throw new Error(\n 'ChainClient.dispatchGasless() cannot bind v3 destination metadata. ' +\n 'Use VeridexSDK.transferViaRelayer() or bridgeViaRelayer().'\n );\n }\n\n async getVaultAddress(userKeyHash: string): Promise<string | null> {\n // Sui vaults may be represented as shared objects on-chain; without registry object IDs,\n // we return the deterministic address used by the SDK for receiving and balance display.\n return this.computeVaultAddress(userKeyHash);\n }\n\n computeVaultAddress(userKeyHash: string): string {\n // SDK convention: Sui addresses are 32-byte hex with 0x prefix.\n const clean = userKeyHash.replace(/^0x/, '').padStart(64, '0');\n return '0x' + clean;\n }\n\n async vaultExists(_userKeyHash: string): Promise<boolean> {\n // Account addresses on Sui are implicit; treat as existing.\n return true;\n }\n\n async createVault(userKeyHash: string, signer: any): Promise<VaultCreationResult> {\n void signer;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n `Use the Hub client to dispatch a vault creation action targeting Sui (chain ${this.config.wormholeChainId}). KeyHash=${userKeyHash}`\n );\n }\n\n async createVaultSponsored?(userKeyHash: string, sponsorPrivateKey: string, rpcUrl?: string): Promise<VaultCreationResult> {\n void userKeyHash;\n void sponsorPrivateKey;\n void rpcUrl;\n throw new Error(\n 'Vault creation on Sui must be done via cross-chain message from Hub. ' +\n 'Use relayer gasless submission to create vault.'\n );\n }\n\n /**\n * Create a vault via the relayer (sponsored/gasless)\n * This is the recommended way to create Sui vaults\n * \n * The relayer will dispatch a vault creation action from Hub to Sui spoke\n */\n async createVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<VaultCreationResult> {\n const response = await fetch(`${relayerUrl}/api/v1/sui/vault`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({\n userKeyHash,\n chainId: this.config.wormholeChainId,\n }),\n });\n\n const result = await response.json();\n\n if (!response.ok || !result.success) {\n throw new Error(result.error || 'Failed to create vault via relayer');\n }\n\n return {\n address: result.vaultAddress,\n transactionHash: result.transactionHash || '',\n blockNumber: 0,\n gasUsed: 0n,\n alreadyExisted: result.alreadyExists || false,\n sponsoredBy: 'relayer',\n };\n }\n\n /**\n * Get vault info via relayer (includes existence check)\n */\n async getVaultViaRelayer(\n userKeyHash: string,\n relayerUrl: string\n ): Promise<{ vaultAddress: string; exists: boolean }> {\n const response = await fetch(\n `${relayerUrl}/api/v1/sui/vault/${userKeyHash}?chainId=${this.config.wormholeChainId}`\n );\n\n if (!response.ok) {\n throw new Error('Failed to get vault info from relayer');\n }\n\n const result = await response.json();\n return {\n vaultAddress: result.vaultAddress,\n exists: result.exists,\n };\n }\n\n async estimateVaultCreationGas(_userKeyHash: string): Promise<bigint> {\n // Best-effort placeholder.\n return 5_000n;\n }\n\n getFactoryAddress(): string | undefined {\n return undefined;\n }\n\n getImplementationAddress(): string | undefined {\n return undefined;\n }\n\n // ========================================================================\n // Balance utilities (used by VeridexSDK multichain)\n // ========================================================================\n\n async getNativeBalance(address: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: address });\n return BigInt(balance.totalBalance);\n }\n\n async getTokenBalance(coinType: string, ownerAddress: string): Promise<bigint> {\n const balance = await this.client.getBalance({ owner: ownerAddress, coinType });\n return BigInt(balance.totalBalance);\n }\n\n getClient(): MystenSuiClient {\n return this.client;\n }\n\n getPackageId(): string {\n return this.packageId;\n }\n\n // ========================================================================\n // Session Management (Issue #13)\n // ========================================================================\n\n /**\n * Register a session key on the Hub (must be called via Hub client)\n * Sui spokes validate sessions via CCQ, but registration happens on Hub\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async registerSession(_params: RegisterSessionParams): Promise<void> {\n throw new Error(\n 'Session registration must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call registerSession().'\n );\n }\n\n /**\n * Revoke a session key on the Hub (must be called via Hub client)\n * \n * @throws Error - Session management must be done via Hub chain\n */\n async revokeSession(_params: RevokeSessionParams): Promise<void> {\n throw new Error(\n 'Session revocation must be performed on the Hub chain (Base). ' +\n 'Use EVMClient connected to the Hub to call revokeSession().'\n );\n }\n\n /**\n * Check if a session is active by querying the Hub\n * This method queries the Hub contract directly for session validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @param sessionKeyHash - Hash of session key to validate\n * @returns Session validation result with expiry and limits\n */\n async isSessionActive(\n _userKeyHash: string,\n _sessionKeyHash: string\n ): Promise<SessionValidationResult> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session validation. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for session status\n // This would normally use ethers.js to query the Hub contract\n // For production, import ethers dynamically or pass Hub client\n throw new Error(\n 'isSessionActive requires Hub client integration. ' +\n 'Use EVMClient.isSessionActive() on the Hub chain, ' +\n 'then pass the result to session execution on Sui.'\n );\n }\n\n /**\n * Get all sessions for a user from the Hub\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Array of all sessions (active and expired/revoked)\n */\n async getUserSessions(userKeyHash: string): Promise<SessionKey[]> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for session queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user sessions\n throw new Error(\n 'getUserSessions requires Hub client integration. ' +\n 'Use EVMClient.getUserSessions() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n // ========================================================================\n // Query-Based Execution (Issue #9/#10)\n // ========================================================================\n\n /**\n * Get user state from Hub (comprehensive state query)\n * Returns key hash, nonce, and last action hash for CCQ validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns User state with nonce and last action hash\n */\n async getUserState(userKeyHash: string): Promise<{\n keyHash: string;\n nonce: bigint;\n lastActionHash: string;\n }> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for state queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for user state\n // This enables query-based execution with CCQ validation\n throw new Error(\n 'getUserState requires Hub client integration. ' +\n 'Use EVMClient.getUserState() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Get user's last action hash from Hub\n * Used for optimistic execution and nonce validation\n * \n * @param userKeyHash - Hash of user's Passkey public key\n * @returns Last action hash (zero hash if no actions)\n */\n async getUserLastActionHash(userKeyHash: string): Promise<string> {\n if (!this.hubRpcUrl || !this.hubContractAddress) {\n throw new Error(\n 'Hub configuration required for action hash queries. ' +\n 'Provide hubRpcUrl and hubContractAddress in SuiClientConfig.'\n );\n }\n\n // Query Hub contract for last action hash\n throw new Error(\n 'getUserLastActionHash requires Hub client integration. ' +\n 'Use EVMClient.getUserLastActionHash() on the Hub chain. ' +\n `User: ${userKeyHash}`\n );\n }\n\n /**\n * Execute with query-based validation (faster than VAA, ~23s vs 60-90s)\n * Uses Wormhole CCQ to validate Hub state, then executes on Sui\n * \n * @param params Query execution parameters with CCQ response\n * @returns Dispatch result with transaction hash\n * \n * @remarks\n * Query-based execution flow:\n * 1. Query Hub state via Wormhole CCQ\n * 2. Validate Guardian signatures on query response\n * 3. Execute on Sui with validated state\n * 4. Hub state must be < 60s stale (enforced by QueryVerifier)\n */\n async executeWithQuery(\n _params: {\n userKeyHash: string;\n queryResponse: Uint8Array; // CCQ Guardian response\n actionType: number;\n actionPayload: Uint8Array;\n relayerUrl?: string;\n }\n ): Promise<DispatchResult> {\n throw new Error(\n 'Query-based execution on Sui requires relayer integration. ' +\n 'Use relayer API to submit query-validated transactions. ' +\n 'Relayer will call veridex_spoke::execute_with_query on Sui.'\n );\n }\n\n // ========================================================================\n // Internal helpers\n // ========================================================================\n\n private computeKeyHash(publicKeyX: bigint, publicKeyY: bigint): string {\n const xHex = publicKeyX.toString(16).padStart(64, '0');\n const yHex = publicKeyY.toString(16).padStart(64, '0');\n const combined = Buffer.from(xHex + yHex, 'hex');\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n private buildMessageHash(keyHash: string, targetChain: number, actionPayload: string, nonce: bigint): string {\n const keyHashBuffer = Buffer.from(keyHash.replace(/^0x/, ''), 'hex');\n const targetChainBuffer = Buffer.alloc(2);\n targetChainBuffer.writeUInt16BE(targetChain);\n const payloadBuffer = Buffer.from(actionPayload.replace(/^0x/, ''), 'hex');\n const nonceHex = nonce.toString(16).padStart(64, '0');\n const nonceBuffer = Buffer.from(nonceHex, 'hex');\n\n const combined = Buffer.concat([keyHashBuffer, targetChainBuffer, payloadBuffer, nonceBuffer]);\n const hash = createHash('sha256').update(combined).digest('hex');\n return '0x' + hash;\n }\n\n // ============================================================================\n // Social Recovery Methods (Issue #23)\n // ============================================================================\n // \n // Note: Social recovery is managed on the Hub chain (EVM).\n // Sui spokes receive and execute recovery VAAs broadcast from the Hub.\n // The relayer service handles submitting recovery transactions to Sui.\n //\n // SDK users should use EVMClient methods for guardian management and\n // recovery initiation on the Hub chain.\n // ============================================================================\n\n /**\n * Get vault object ID by owner key hash\n * \n * @param ownerKeyHash - Owner's passkey hash (32 bytes as hex)\n * @param configObjectId - Shared Config object ID\n * @param registryObjectId - Shared VaultRegistry object ID\n * @returns Vault object ID or null if not found\n */\n async getVaultId(\n _ownerKeyHash: string,\n registryObjectId: string\n ): Promise<string | null> {\n try {\n // Query the VaultRegistry table for the owner_key_hash\n // The registry maps owner_key_hash -> vault ID\n const registryObject = await this.client.getObject({\n id: registryObjectId,\n options: { showContent: true },\n });\n\n if (!registryObject.data?.content) {\n return null;\n }\n\n // For a proper implementation, we'd need to query dynamic fields\n // or use a Move view function. This is a placeholder showing the pattern.\n console.warn('getVaultId requires dynamic field query - use Move view function');\n return null;\n } catch (error) {\n console.error('Error getting vault ID:', error);\n return null;\n }\n }\n\n /**\n * Get vault owner key hash from vault object\n * \n * @param vaultObjectId - Vault object ID\n * @returns Owner key hash as hex string\n */\n async getVaultOwner(vaultObjectId: string): Promise<string | null> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return null;\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const ownerKeyHash = fields['owner_key_hash'] as number[] | undefined;\n\n if (!ownerKeyHash) {\n return null;\n }\n\n // Convert byte array to hex string\n return '0x' + Buffer.from(ownerKeyHash).toString('hex');\n } catch (error) {\n console.error('Error getting vault owner:', error);\n return null;\n }\n }\n\n /**\n * Get authorized signers for a vault\n * \n * @param vaultObjectId - Vault object ID\n * @returns Array of authorized signer key hashes\n */\n async getAuthorizedSigners(vaultObjectId: string): Promise<string[]> {\n try {\n const vaultObject = await this.client.getObject({\n id: vaultObjectId,\n options: { showContent: true },\n });\n\n if (!vaultObject.data?.content || vaultObject.data.content.dataType !== 'moveObject') {\n return [];\n }\n\n const fields = vaultObject.data.content.fields as Record<string, unknown>;\n const authorizedSigners = fields['authorized_signers'] as number[][] | undefined;\n\n if (!authorizedSigners) {\n return [];\n }\n\n // Convert each byte array to hex string\n return authorizedSigners.map(signer => \n '0x' + Buffer.from(signer).toString('hex')\n );\n } catch (error) {\n console.error('Error getting authorized signers:', error);\n return [];\n }\n }\n\n /**\n * Check if a VAA has been processed (for replay protection)\n * \n * @param vaaHash - VAA hash as hex string\n * @param processedVaasObjectId - ProcessedVAAs shared object ID\n * @returns Whether the VAA has been processed\n */\n async isVaaProcessed(\n _vaaHash: string,\n processedVaasObjectId: string\n ): Promise<boolean> {\n try {\n const processedObject = await this.client.getObject({\n id: processedVaasObjectId,\n options: { showContent: true },\n });\n\n if (!processedObject.data?.content) {\n return false;\n }\n\n // Would need to query dynamic field for vaaHash key\n console.warn('isVaaProcessed requires dynamic field query');\n return false;\n } catch (error) {\n console.error('Error checking VAA status:', error);\n return false;\n }\n }\n\n /**\n * Check if protocol is paused\n * \n * @param configObjectId - Config shared object ID\n * @returns Whether the protocol is paused\n */\n async isProtocolPaused(configObjectId: string): Promise<boolean> {\n try {\n const configObject = await this.client.getObject({\n id: configObjectId,\n options: { showContent: true },\n });\n\n if (!configObject.data?.content || configObject.data.content.dataType !== 'moveObject') {\n return false;\n }\n\n const fields = configObject.data.content.fields as Record<string, unknown>;\n return fields['paused'] === true;\n } catch (error) {\n console.error('Error checking pause status:', error);\n return false;\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildRelayerApiUrl,
|
|
3
|
+
normalizeRelayerOrigin
|
|
4
|
+
} from "./chunk-WC4X3MAO.mjs";
|
|
1
5
|
import {
|
|
2
6
|
base64URLDecode,
|
|
3
7
|
base64URLEncode,
|
|
@@ -12,61 +16,6 @@ import {
|
|
|
12
16
|
browserSupportsWebAuthn
|
|
13
17
|
} from "@simplewebauthn/browser";
|
|
14
18
|
import { ethers } from "ethers";
|
|
15
|
-
|
|
16
|
-
// src/core/relayerUrl.ts
|
|
17
|
-
var API_ROOT = "/api/v1";
|
|
18
|
-
function trimTrailingSlashes(value) {
|
|
19
|
-
return value.trim().replace(/\/+$/, "");
|
|
20
|
-
}
|
|
21
|
-
function normalizeRelayerOrigin(value) {
|
|
22
|
-
const trimmed = trimTrailingSlashes(value);
|
|
23
|
-
if (!trimmed) {
|
|
24
|
-
return "";
|
|
25
|
-
}
|
|
26
|
-
if (trimmed.startsWith("/")) {
|
|
27
|
-
return trimmed.replace(/\/api\/v1$/i, "");
|
|
28
|
-
}
|
|
29
|
-
try {
|
|
30
|
-
const url = new URL(trimmed);
|
|
31
|
-
url.pathname = url.pathname.replace(/\/api\/v1$/i, "").replace(/\/+$/, "");
|
|
32
|
-
return url.toString().replace(/\/+$/, "");
|
|
33
|
-
} catch {
|
|
34
|
-
return trimmed.replace(/\/api\/v1$/i, "");
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
function buildRelayerApiUrl(baseUrl, path) {
|
|
38
|
-
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
39
|
-
const trimmed = trimTrailingSlashes(baseUrl);
|
|
40
|
-
if (!trimmed) {
|
|
41
|
-
return `${API_ROOT}${normalizedPath}`;
|
|
42
|
-
}
|
|
43
|
-
if (trimmed.startsWith("/")) {
|
|
44
|
-
if (/\/api\/v1$/i.test(trimmed) || /\/api\/auth\/relay$/i.test(trimmed)) {
|
|
45
|
-
return `${trimmed}${normalizedPath}`;
|
|
46
|
-
}
|
|
47
|
-
return `${trimmed}${normalizedPath}`;
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
const url = new URL(trimmed);
|
|
51
|
-
if (/\/api\/v1$/i.test(url.pathname) || /\/api\/auth\/relay$/i.test(url.pathname)) {
|
|
52
|
-
url.pathname = `${url.pathname.replace(/\/+$/, "")}${normalizedPath}`;
|
|
53
|
-
return url.toString();
|
|
54
|
-
}
|
|
55
|
-
if (!url.pathname || url.pathname === "/") {
|
|
56
|
-
url.pathname = `${API_ROOT}${normalizedPath}`;
|
|
57
|
-
return url.toString();
|
|
58
|
-
}
|
|
59
|
-
url.pathname = `${url.pathname.replace(/\/+$/, "")}${normalizedPath}`;
|
|
60
|
-
return url.toString();
|
|
61
|
-
} catch {
|
|
62
|
-
if (/\/api\/v1$/i.test(trimmed) || /\/api\/auth\/relay$/i.test(trimmed)) {
|
|
63
|
-
return `${trimmed}${normalizedPath}`;
|
|
64
|
-
}
|
|
65
|
-
return `${trimmed}${API_ROOT}${normalizedPath}`;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// src/core/PasskeyManager.ts
|
|
70
19
|
var VERIDEX_RP_ID = "veridex.network";
|
|
71
20
|
function detectRpId(forceLocal) {
|
|
72
21
|
if (typeof window === "undefined") return "localhost";
|
|
@@ -167,7 +116,8 @@ var PasskeyManager = class _PasskeyManager {
|
|
|
167
116
|
credentialId: response.id,
|
|
168
117
|
publicKeyX: publicKey.x,
|
|
169
118
|
publicKeyY: publicKey.y,
|
|
170
|
-
keyHash
|
|
119
|
+
keyHash,
|
|
120
|
+
assurance: _PasskeyManager.assuranceFromRegistration(response) ?? void 0
|
|
171
121
|
};
|
|
172
122
|
return this.credential;
|
|
173
123
|
}
|
|
@@ -546,7 +496,8 @@ var PasskeyManager = class _PasskeyManager {
|
|
|
546
496
|
credentialId: response.id,
|
|
547
497
|
publicKeyX: publicKey.x,
|
|
548
498
|
publicKeyY: publicKey.y,
|
|
549
|
-
keyHash
|
|
499
|
+
keyHash,
|
|
500
|
+
assurance: _PasskeyManager.assuranceFromRegistration(response) ?? void 0
|
|
550
501
|
};
|
|
551
502
|
this.addCredentialToStorage(backupCredential);
|
|
552
503
|
return backupCredential;
|
|
@@ -563,17 +514,94 @@ var PasskeyManager = class _PasskeyManager {
|
|
|
563
514
|
*/
|
|
564
515
|
static parseBackupFlags(authenticatorData) {
|
|
565
516
|
try {
|
|
566
|
-
const
|
|
567
|
-
if (
|
|
568
|
-
const flags = data[32];
|
|
517
|
+
const assurance = _PasskeyManager.deriveAssurance(ethers.getBytes(authenticatorData));
|
|
518
|
+
if (!assurance) return null;
|
|
569
519
|
return {
|
|
570
|
-
backupEligible:
|
|
571
|
-
backupState:
|
|
520
|
+
backupEligible: assurance.backupEligible,
|
|
521
|
+
backupState: assurance.backupState
|
|
572
522
|
};
|
|
573
523
|
} catch {
|
|
574
524
|
return null;
|
|
575
525
|
}
|
|
576
526
|
}
|
|
527
|
+
/**
|
|
528
|
+
* Derive credential assurance from raw WebAuthn authenticator data.
|
|
529
|
+
*
|
|
530
|
+
* authData layout:
|
|
531
|
+
* rpIdHash (32) | flags (1) | signCount (4) | [attestedCredentialData: aaguid (16) | ...]
|
|
532
|
+
*
|
|
533
|
+
* Flags byte: UP 0x01 | UV 0x04 | BE 0x08 | BS 0x10 | AT 0x40 | ED 0x80
|
|
534
|
+
*
|
|
535
|
+
* BE is the authoritative signal for whether a credential is device-bound or
|
|
536
|
+
* syncable. It is set by the authenticator itself — unlike a platform/user-agent
|
|
537
|
+
* guess, it correctly identifies a hardware key used on a syncing platform.
|
|
538
|
+
*
|
|
539
|
+
* @returns Assurance, or `null` if authData is too short to be valid.
|
|
540
|
+
*/
|
|
541
|
+
static deriveAssurance(authData) {
|
|
542
|
+
if (authData.length < 37) return null;
|
|
543
|
+
const flags = authData[32];
|
|
544
|
+
const backupEligible = (flags & 8) !== 0;
|
|
545
|
+
const attestedCredentialData = (flags & 64) !== 0;
|
|
546
|
+
let aaguid;
|
|
547
|
+
if (attestedCredentialData && authData.length >= 53) {
|
|
548
|
+
aaguid = ethers.hexlify(authData.slice(37, 53));
|
|
549
|
+
}
|
|
550
|
+
return {
|
|
551
|
+
backupEligible,
|
|
552
|
+
backupState: (flags & 16) !== 0,
|
|
553
|
+
userVerified: (flags & 4) !== 0,
|
|
554
|
+
level: backupEligible ? "synced" : "device-bound",
|
|
555
|
+
aaguid
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Extract raw authenticator data from a registration response.
|
|
560
|
+
*
|
|
561
|
+
* Prefers the `authenticatorData` field when the authenticator provides it,
|
|
562
|
+
* and otherwise locates the `authData` byte string inside the CBOR
|
|
563
|
+
* attestation object.
|
|
564
|
+
*/
|
|
565
|
+
static extractAuthData(response) {
|
|
566
|
+
const direct = response.response.authenticatorData;
|
|
567
|
+
if (direct) {
|
|
568
|
+
try {
|
|
569
|
+
return base64URLDecode(direct);
|
|
570
|
+
} catch {
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
try {
|
|
574
|
+
const attestationObject = base64URLDecode(response.response.attestationObject);
|
|
575
|
+
let offset = 0;
|
|
576
|
+
if (attestationObject[offset] >= 160 && attestationObject[offset] <= 191) {
|
|
577
|
+
offset++;
|
|
578
|
+
}
|
|
579
|
+
const key = [104, 97, 117, 116, 104, 68, 97, 116, 97];
|
|
580
|
+
let found = false;
|
|
581
|
+
while (offset < attestationObject.length - 37) {
|
|
582
|
+
if (key.every((byte, i) => attestationObject[offset + i] === byte)) {
|
|
583
|
+
offset += key.length;
|
|
584
|
+
found = true;
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
587
|
+
offset++;
|
|
588
|
+
}
|
|
589
|
+
if (!found) return null;
|
|
590
|
+
if (attestationObject[offset] === 88) {
|
|
591
|
+
offset += 2;
|
|
592
|
+
} else if (attestationObject[offset] === 89) {
|
|
593
|
+
offset += 3;
|
|
594
|
+
}
|
|
595
|
+
return attestationObject.slice(offset);
|
|
596
|
+
} catch {
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
/** Derive assurance directly from a registration response. */
|
|
601
|
+
static assuranceFromRegistration(response) {
|
|
602
|
+
const authData = _PasskeyManager.extractAuthData(response);
|
|
603
|
+
return authData ? _PasskeyManager.deriveAssurance(authData) : null;
|
|
604
|
+
}
|
|
577
605
|
/**
|
|
578
606
|
* Get the number of credentials stored locally.
|
|
579
607
|
*/
|
|
@@ -876,11 +904,9 @@ var PasskeyManager = class _PasskeyManager {
|
|
|
876
904
|
};
|
|
877
905
|
|
|
878
906
|
export {
|
|
879
|
-
normalizeRelayerOrigin,
|
|
880
|
-
buildRelayerApiUrl,
|
|
881
907
|
VERIDEX_RP_ID,
|
|
882
908
|
detectRpId,
|
|
883
909
|
supportsRelatedOrigins,
|
|
884
910
|
PasskeyManager
|
|
885
911
|
};
|
|
886
|
-
//# sourceMappingURL=chunk-
|
|
912
|
+
//# sourceMappingURL=chunk-SKZLZFE2.mjs.map
|