@outlayer/sdk 0.1.0-alpha.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/LICENSE +21 -0
- package/README.md +207 -0
- package/dist/index.cjs +389 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1788 -0
- package/dist/index.d.ts +1788 -0
- package/dist/index.js +373 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/spec/openapi.yaml +1648 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import createClient from 'openapi-fetch';
|
|
2
|
+
|
|
3
|
+
// src/http.ts
|
|
4
|
+
|
|
5
|
+
// src/errors.ts
|
|
6
|
+
var OutlayerError = class extends Error {
|
|
7
|
+
code;
|
|
8
|
+
status;
|
|
9
|
+
details;
|
|
10
|
+
constructor(opts) {
|
|
11
|
+
super(opts.message);
|
|
12
|
+
this.name = "OutlayerError";
|
|
13
|
+
this.code = opts.code;
|
|
14
|
+
this.status = opts.status;
|
|
15
|
+
this.details = opts.details;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
var PolicyDeniedError = class extends OutlayerError {
|
|
19
|
+
constructor(opts) {
|
|
20
|
+
super(opts);
|
|
21
|
+
this.name = "PolicyDeniedError";
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
var WalletFrozenError = class extends OutlayerError {
|
|
25
|
+
constructor(opts) {
|
|
26
|
+
super(opts);
|
|
27
|
+
this.name = "WalletFrozenError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
var UnauthorizedError = class extends OutlayerError {
|
|
31
|
+
constructor(opts) {
|
|
32
|
+
super(opts);
|
|
33
|
+
this.name = "UnauthorizedError";
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
var RateLimitedError = class extends OutlayerError {
|
|
37
|
+
constructor(opts) {
|
|
38
|
+
super(opts);
|
|
39
|
+
this.name = "RateLimitedError";
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var NotFoundError = class extends OutlayerError {
|
|
43
|
+
constructor(opts) {
|
|
44
|
+
super(opts);
|
|
45
|
+
this.name = "NotFoundError";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var BadRequestError = class extends OutlayerError {
|
|
49
|
+
constructor(opts) {
|
|
50
|
+
super(opts);
|
|
51
|
+
this.name = "BadRequestError";
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var codeToCtor = {
|
|
55
|
+
policy_denied: PolicyDeniedError,
|
|
56
|
+
wallet_frozen: WalletFrozenError,
|
|
57
|
+
missing_auth: UnauthorizedError,
|
|
58
|
+
invalid_api_key: UnauthorizedError,
|
|
59
|
+
timestamp_expired: UnauthorizedError,
|
|
60
|
+
rate_limited: RateLimitedError,
|
|
61
|
+
request_not_found: NotFoundError,
|
|
62
|
+
approval_not_found: NotFoundError,
|
|
63
|
+
bad_request: BadRequestError,
|
|
64
|
+
invalid_address: BadRequestError,
|
|
65
|
+
insufficient_balance: BadRequestError,
|
|
66
|
+
unsupported_chain: BadRequestError,
|
|
67
|
+
unsupported_token: BadRequestError
|
|
68
|
+
};
|
|
69
|
+
function makeError(body, status) {
|
|
70
|
+
const code = body.error ?? "parse_error";
|
|
71
|
+
const message = body.message ?? `HTTP ${status}`;
|
|
72
|
+
const opts = body.details !== void 0 ? { code, message, status, details: body.details } : { code, message, status };
|
|
73
|
+
const Ctor = codeToCtor[code] ?? OutlayerError;
|
|
74
|
+
return new Ctor(opts);
|
|
75
|
+
}
|
|
76
|
+
async function errorFromResponse(response, parsed) {
|
|
77
|
+
let body;
|
|
78
|
+
if (parsed && typeof parsed === "object") {
|
|
79
|
+
body = parsed;
|
|
80
|
+
} else {
|
|
81
|
+
try {
|
|
82
|
+
body = await response.clone().json();
|
|
83
|
+
} catch {
|
|
84
|
+
body = { error: "internal_error", message: response.statusText };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return makeError(body, response.status);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/http.ts
|
|
91
|
+
var DEFAULT_BASE_URL = "https://api.outlayer.fastnear.com";
|
|
92
|
+
var DEFAULT_RETRY = {
|
|
93
|
+
maxAttempts: 3,
|
|
94
|
+
initialDelayMs: 100,
|
|
95
|
+
maxDelayMs: 1600
|
|
96
|
+
};
|
|
97
|
+
function makeClient(opts) {
|
|
98
|
+
const init = {
|
|
99
|
+
baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,
|
|
100
|
+
headers: { Authorization: `Bearer ${opts.apiKey}` }
|
|
101
|
+
};
|
|
102
|
+
if (opts.fetch) init.fetch = opts.fetch;
|
|
103
|
+
const client = createClient(init);
|
|
104
|
+
const retry = { ...DEFAULT_RETRY, ...opts.retry };
|
|
105
|
+
return { client, retry };
|
|
106
|
+
}
|
|
107
|
+
function makeUnauthenticatedClient(opts = {}) {
|
|
108
|
+
const init = {
|
|
109
|
+
baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL
|
|
110
|
+
};
|
|
111
|
+
if (opts.fetch) init.fetch = opts.fetch;
|
|
112
|
+
return createClient(init);
|
|
113
|
+
}
|
|
114
|
+
async function runWithRetry(call, retry) {
|
|
115
|
+
let lastError;
|
|
116
|
+
for (let attempt = 1; attempt <= retry.maxAttempts; attempt++) {
|
|
117
|
+
try {
|
|
118
|
+
const { data, error, response } = await call();
|
|
119
|
+
if (response.ok) {
|
|
120
|
+
return data;
|
|
121
|
+
}
|
|
122
|
+
const err = await errorFromResponse(response, error);
|
|
123
|
+
if (err.status >= 500 && attempt < retry.maxAttempts) {
|
|
124
|
+
lastError = err;
|
|
125
|
+
await sleep(backoff(attempt, retry));
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
throw err;
|
|
129
|
+
} catch (e) {
|
|
130
|
+
if (e instanceof OutlayerError) throw e;
|
|
131
|
+
lastError = e;
|
|
132
|
+
if (attempt < retry.maxAttempts && isNetworkError(e)) {
|
|
133
|
+
await sleep(backoff(attempt, retry));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
throw new OutlayerError({
|
|
137
|
+
code: "network_error",
|
|
138
|
+
message: e instanceof Error ? e.message : String(e),
|
|
139
|
+
status: 0
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
throw lastError;
|
|
144
|
+
}
|
|
145
|
+
function backoff(attempt, cfg) {
|
|
146
|
+
return Math.min(cfg.maxDelayMs, cfg.initialDelayMs * 2 ** (attempt - 1));
|
|
147
|
+
}
|
|
148
|
+
function sleep(ms) {
|
|
149
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
150
|
+
}
|
|
151
|
+
function isNetworkError(e) {
|
|
152
|
+
return e instanceof TypeError;
|
|
153
|
+
}
|
|
154
|
+
function newIdempotencyKey() {
|
|
155
|
+
return crypto.randomUUID();
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/client.ts
|
|
159
|
+
function idempotencyHeader(key) {
|
|
160
|
+
return { "Idempotency-Key": key ?? newIdempotencyKey() };
|
|
161
|
+
}
|
|
162
|
+
var PolicyAPI = class {
|
|
163
|
+
constructor(client, retry) {
|
|
164
|
+
this.client = client;
|
|
165
|
+
this.retry = retry;
|
|
166
|
+
}
|
|
167
|
+
client;
|
|
168
|
+
retry;
|
|
169
|
+
get() {
|
|
170
|
+
return runWithRetry(() => this.client.GET("/wallet/v1/policy"), this.retry);
|
|
171
|
+
}
|
|
172
|
+
encrypt(body) {
|
|
173
|
+
return runWithRetry(() => this.client.POST("/wallet/v1/encrypt-policy", { body }), this.retry);
|
|
174
|
+
}
|
|
175
|
+
sign(encryptedData) {
|
|
176
|
+
return runWithRetry(
|
|
177
|
+
() => this.client.POST("/wallet/v1/sign-policy", { body: { encrypted_data: encryptedData } }),
|
|
178
|
+
this.retry
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
invalidateCache(walletId) {
|
|
182
|
+
return runWithRetry(
|
|
183
|
+
() => this.client.POST("/wallet/v1/invalidate-cache", { body: { wallet_id: walletId } }),
|
|
184
|
+
this.retry
|
|
185
|
+
).then(() => void 0);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
var ApprovalsAPI = class {
|
|
189
|
+
constructor(client, retry) {
|
|
190
|
+
this.client = client;
|
|
191
|
+
this.retry = retry;
|
|
192
|
+
}
|
|
193
|
+
client;
|
|
194
|
+
retry;
|
|
195
|
+
listPending() {
|
|
196
|
+
return runWithRetry(() => this.client.GET("/wallet/v1/pending_approvals"), this.retry);
|
|
197
|
+
}
|
|
198
|
+
approve(approvalId, auth) {
|
|
199
|
+
return runWithRetry(
|
|
200
|
+
() => this.client.POST("/wallet/v1/approve/{id}", {
|
|
201
|
+
params: { path: { id: approvalId } },
|
|
202
|
+
body: auth
|
|
203
|
+
}),
|
|
204
|
+
this.retry
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
reject(approvalId, auth, reason) {
|
|
208
|
+
const body = reason !== void 0 ? { ...auth, reason } : auth;
|
|
209
|
+
return runWithRetry(
|
|
210
|
+
() => this.client.POST("/wallet/v1/reject/{id}", {
|
|
211
|
+
params: { path: { id: approvalId } },
|
|
212
|
+
body
|
|
213
|
+
}),
|
|
214
|
+
this.retry
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
var AuditAPI = class {
|
|
219
|
+
constructor(client, retry) {
|
|
220
|
+
this.client = client;
|
|
221
|
+
this.retry = retry;
|
|
222
|
+
}
|
|
223
|
+
client;
|
|
224
|
+
retry;
|
|
225
|
+
list(opts = {}) {
|
|
226
|
+
return runWithRetry(
|
|
227
|
+
() => this.client.GET("/wallet/v1/audit", { params: { query: opts } }),
|
|
228
|
+
this.retry
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
var OutlayerClient = class {
|
|
233
|
+
client;
|
|
234
|
+
retry;
|
|
235
|
+
policy;
|
|
236
|
+
approvals;
|
|
237
|
+
audit;
|
|
238
|
+
constructor(opts) {
|
|
239
|
+
const { client, retry } = makeClient(opts);
|
|
240
|
+
this.client = client;
|
|
241
|
+
this.retry = retry;
|
|
242
|
+
this.policy = new PolicyAPI(client, retry);
|
|
243
|
+
this.approvals = new ApprovalsAPI(client, retry);
|
|
244
|
+
this.audit = new AuditAPI(client, retry);
|
|
245
|
+
}
|
|
246
|
+
// ------- Static factory: register a new wallet (no auth) -------
|
|
247
|
+
/**
|
|
248
|
+
* Register a new wallet and obtain an API key.
|
|
249
|
+
*
|
|
250
|
+
* - Empty call: anonymous wallet on OutLayer's shared master. Convenient, no setup.
|
|
251
|
+
* - With `vaultId`: bind to a deployed customer vault so keys derive through
|
|
252
|
+
* the per-vault master. Vault binding is permanent.
|
|
253
|
+
* - With `body`: full control — pass any `RegisterRequest` field (e.g., NEP-413
|
|
254
|
+
* account-binding fields). `vaultId` is merged into `body.vault_id` if not
|
|
255
|
+
* already set.
|
|
256
|
+
*
|
|
257
|
+
* Vault deployment is NOT done here — use the dashboard
|
|
258
|
+
* (https://outlayer.fastnear.com/vault) or `outlayer vault init` CLI.
|
|
259
|
+
* See docs/vaults.md for the full flow.
|
|
260
|
+
*/
|
|
261
|
+
static async register(opts = {}) {
|
|
262
|
+
const client = makeUnauthenticatedClient(opts);
|
|
263
|
+
const body = { ...opts.body ?? {} };
|
|
264
|
+
if (opts.vaultId !== void 0 && body.vault_id === void 0) {
|
|
265
|
+
body.vault_id = opts.vaultId;
|
|
266
|
+
}
|
|
267
|
+
const { data, error, response } = await client.POST("/register", { body });
|
|
268
|
+
if (!response.ok) throw await errorFromResponse(response, error);
|
|
269
|
+
return data;
|
|
270
|
+
}
|
|
271
|
+
// ------- Wallet read -------
|
|
272
|
+
getAddress(chain) {
|
|
273
|
+
return runWithRetry(
|
|
274
|
+
() => this.client.GET("/wallet/v1/address", { params: { query: { chain } } }),
|
|
275
|
+
this.retry
|
|
276
|
+
);
|
|
277
|
+
}
|
|
278
|
+
getBalance(opts = {}) {
|
|
279
|
+
return runWithRetry(
|
|
280
|
+
() => this.client.GET("/wallet/v1/balance", { params: { query: opts } }),
|
|
281
|
+
this.retry
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
listTokens() {
|
|
285
|
+
return runWithRetry(() => this.client.GET("/wallet/v1/tokens"), this.retry);
|
|
286
|
+
}
|
|
287
|
+
// ------- Wallet write -------
|
|
288
|
+
call(opts) {
|
|
289
|
+
const { idempotencyKey, ...body } = opts;
|
|
290
|
+
return runWithRetry(
|
|
291
|
+
() => this.client.POST("/wallet/v1/call", {
|
|
292
|
+
body,
|
|
293
|
+
headers: idempotencyHeader(idempotencyKey)
|
|
294
|
+
}),
|
|
295
|
+
this.retry
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
transfer(opts) {
|
|
299
|
+
const { idempotencyKey, ...body } = opts;
|
|
300
|
+
return runWithRetry(
|
|
301
|
+
() => this.client.POST("/wallet/v1/transfer", {
|
|
302
|
+
body,
|
|
303
|
+
headers: idempotencyHeader(idempotencyKey)
|
|
304
|
+
}),
|
|
305
|
+
this.retry
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
intentsDeposit(opts) {
|
|
309
|
+
const { idempotencyKey, ...body } = opts;
|
|
310
|
+
return runWithRetry(
|
|
311
|
+
() => this.client.POST("/wallet/v1/intents/deposit", {
|
|
312
|
+
body,
|
|
313
|
+
headers: idempotencyHeader(idempotencyKey)
|
|
314
|
+
}),
|
|
315
|
+
this.retry
|
|
316
|
+
);
|
|
317
|
+
}
|
|
318
|
+
withdraw(opts) {
|
|
319
|
+
const { idempotencyKey, ...body } = opts;
|
|
320
|
+
return runWithRetry(
|
|
321
|
+
() => this.client.POST("/wallet/v1/intents/withdraw", {
|
|
322
|
+
body,
|
|
323
|
+
headers: idempotencyHeader(idempotencyKey)
|
|
324
|
+
}),
|
|
325
|
+
this.retry
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
withdrawDryRun(opts) {
|
|
329
|
+
return runWithRetry(
|
|
330
|
+
() => this.client.POST("/wallet/v1/intents/withdraw/dry-run", { body: opts }),
|
|
331
|
+
this.retry
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
swap(opts) {
|
|
335
|
+
const { idempotencyKey, ...body } = opts;
|
|
336
|
+
return runWithRetry(
|
|
337
|
+
() => this.client.POST("/wallet/v1/intents/swap", {
|
|
338
|
+
body,
|
|
339
|
+
headers: idempotencyHeader(idempotencyKey)
|
|
340
|
+
}),
|
|
341
|
+
this.retry
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
swapQuote(opts) {
|
|
345
|
+
return runWithRetry(
|
|
346
|
+
() => this.client.POST("/wallet/v1/intents/swap/quote", { body: opts }),
|
|
347
|
+
this.retry
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
signMessage(opts) {
|
|
351
|
+
return runWithRetry(
|
|
352
|
+
() => this.client.POST("/wallet/v1/sign-message", { body: opts }),
|
|
353
|
+
this.retry
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
// ------- Async request tracking -------
|
|
357
|
+
getRequest(id) {
|
|
358
|
+
return runWithRetry(
|
|
359
|
+
() => this.client.GET("/wallet/v1/requests/{id}", { params: { path: { id } } }),
|
|
360
|
+
this.retry
|
|
361
|
+
);
|
|
362
|
+
}
|
|
363
|
+
listRequests(opts = {}) {
|
|
364
|
+
return runWithRetry(
|
|
365
|
+
() => this.client.GET("/wallet/v1/requests", { params: { query: opts } }),
|
|
366
|
+
this.retry
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
export { ApprovalsAPI, AuditAPI, BadRequestError, NotFoundError, OutlayerClient, OutlayerError, PolicyAPI, PolicyDeniedError, RateLimitedError, UnauthorizedError, WalletFrozenError };
|
|
372
|
+
//# sourceMappingURL=index.js.map
|
|
373
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/http.ts","../src/client.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { components } from './types.js';\n\nexport type ApiErrorCode = components['schemas']['ErrorCode'];\nexport type ErrorCode = ApiErrorCode | 'network_error' | 'parse_error';\n\nexport type ErrorBody = {\n error?: ApiErrorCode;\n message?: string;\n details?: unknown;\n};\n\nexport interface OutlayerErrorOptions {\n code: ErrorCode;\n message: string;\n status: number;\n details?: unknown;\n}\n\nexport class OutlayerError extends Error {\n readonly code: ErrorCode;\n readonly status: number;\n readonly details: unknown;\n\n constructor(opts: OutlayerErrorOptions) {\n super(opts.message);\n this.name = 'OutlayerError';\n this.code = opts.code;\n this.status = opts.status;\n this.details = opts.details;\n }\n}\n\nexport class PolicyDeniedError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'PolicyDeniedError';\n }\n}\n\nexport class WalletFrozenError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'WalletFrozenError';\n }\n}\n\nexport class UnauthorizedError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'UnauthorizedError';\n }\n}\n\nexport class RateLimitedError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'RateLimitedError';\n }\n}\n\nexport class NotFoundError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'NotFoundError';\n }\n}\n\nexport class BadRequestError extends OutlayerError {\n constructor(opts: OutlayerErrorOptions) {\n super(opts);\n this.name = 'BadRequestError';\n }\n}\n\nconst codeToCtor: Partial<Record<ErrorCode, new (opts: OutlayerErrorOptions) => OutlayerError>> = {\n policy_denied: PolicyDeniedError,\n wallet_frozen: WalletFrozenError,\n missing_auth: UnauthorizedError,\n invalid_api_key: UnauthorizedError,\n timestamp_expired: UnauthorizedError,\n rate_limited: RateLimitedError,\n request_not_found: NotFoundError,\n approval_not_found: NotFoundError,\n bad_request: BadRequestError,\n invalid_address: BadRequestError,\n insufficient_balance: BadRequestError,\n unsupported_chain: BadRequestError,\n unsupported_token: BadRequestError,\n};\n\nexport function makeError(body: ErrorBody, status: number): OutlayerError {\n const code: ErrorCode = body.error ?? 'parse_error';\n const message = body.message ?? `HTTP ${status}`;\n const opts: OutlayerErrorOptions = body.details !== undefined\n ? { code, message, status, details: body.details }\n : { code, message, status };\n const Ctor = codeToCtor[code] ?? OutlayerError;\n return new Ctor(opts);\n}\n\nexport async function errorFromResponse(response: Response, parsed?: unknown): Promise<OutlayerError> {\n let body: ErrorBody;\n if (parsed && typeof parsed === 'object') {\n body = parsed as ErrorBody;\n } else {\n try {\n body = (await response.clone().json()) as ErrorBody;\n } catch {\n body = { error: 'internal_error', message: response.statusText };\n }\n }\n return makeError(body, response.status);\n}\n","import createClient, { type Client } from 'openapi-fetch';\nimport type { paths } from './types.js';\nimport { OutlayerError, errorFromResponse } from './errors.js';\n\nexport const DEFAULT_BASE_URL = 'https://api.outlayer.fastnear.com';\n\nexport type RetryConfig = {\n maxAttempts?: number;\n initialDelayMs?: number;\n maxDelayMs?: number;\n};\n\nexport type ClientOptions = {\n apiKey: string;\n baseUrl?: string;\n fetch?: typeof fetch;\n retry?: RetryConfig;\n};\n\nexport type UnauthenticatedOptions = {\n baseUrl?: string;\n fetch?: typeof fetch;\n};\n\nexport const DEFAULT_RETRY: Required<RetryConfig> = {\n maxAttempts: 3,\n initialDelayMs: 100,\n maxDelayMs: 1600,\n};\n\nexport type FetchClient = Client<paths, `${string}/${string}`>;\n\nexport function makeClient(opts: ClientOptions): { client: FetchClient; retry: Required<RetryConfig> } {\n const init: Parameters<typeof createClient<paths>>[0] = {\n baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,\n headers: { Authorization: `Bearer ${opts.apiKey}` },\n };\n if (opts.fetch) init.fetch = opts.fetch;\n const client = createClient<paths>(init);\n const retry: Required<RetryConfig> = { ...DEFAULT_RETRY, ...opts.retry };\n return { client, retry };\n}\n\nexport function makeUnauthenticatedClient(opts: UnauthenticatedOptions = {}): FetchClient {\n const init: Parameters<typeof createClient<paths>>[0] = {\n baseUrl: opts.baseUrl ?? DEFAULT_BASE_URL,\n };\n if (opts.fetch) init.fetch = opts.fetch;\n return createClient<paths>(init);\n}\n\nexport type FetchCall<T> = () => Promise<{\n data?: T;\n error?: unknown;\n response: Response;\n}>;\n\nexport async function runWithRetry<T>(\n call: FetchCall<T>,\n retry: Required<RetryConfig>,\n): Promise<T> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= retry.maxAttempts; attempt++) {\n try {\n const { data, error, response } = await call();\n if (response.ok) {\n return data as T;\n }\n const err = await errorFromResponse(response, error);\n if (err.status >= 500 && attempt < retry.maxAttempts) {\n lastError = err;\n await sleep(backoff(attempt, retry));\n continue;\n }\n throw err;\n } catch (e) {\n if (e instanceof OutlayerError) throw e;\n lastError = e;\n if (attempt < retry.maxAttempts && isNetworkError(e)) {\n await sleep(backoff(attempt, retry));\n continue;\n }\n throw new OutlayerError({\n code: 'network_error',\n message: e instanceof Error ? e.message : String(e),\n status: 0,\n });\n }\n }\n throw lastError;\n}\n\nfunction backoff(attempt: number, cfg: Required<RetryConfig>): number {\n return Math.min(cfg.maxDelayMs, cfg.initialDelayMs * 2 ** (attempt - 1));\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((r) => setTimeout(r, ms));\n}\n\nfunction isNetworkError(e: unknown): boolean {\n return e instanceof TypeError;\n}\n\nexport function newIdempotencyKey(): string {\n return crypto.randomUUID();\n}\n","import type { components } from './types.js';\nimport {\n type ClientOptions,\n type FetchClient,\n type RetryConfig,\n type UnauthenticatedOptions,\n DEFAULT_RETRY,\n makeClient,\n makeUnauthenticatedClient,\n newIdempotencyKey,\n runWithRetry,\n} from './http.js';\nimport { errorFromResponse } from './errors.js';\n\ntype Schemas = components['schemas'];\n\n// ---------------------------------------------------------------------------\n// Re-exported user-facing types (so consumers don't import paths/components)\n// ---------------------------------------------------------------------------\n\nexport type Chain = Schemas['Chain'];\nexport type RequestType = Schemas['RequestType'];\nexport type RequestStatus = Schemas['RequestStatus'];\n\nexport type RegisterRequest = Schemas['RegisterRequest'];\nexport type RegisterResponse = Schemas['RegisterResponse'];\nexport type AddressResponse = Schemas['AddressResponse'];\nexport type BalanceResponse = Schemas['BalanceResponse'];\nexport type TokensResponse = Schemas['TokensResponse'];\n\nexport type CallRequest = Schemas['CallRequest'];\nexport type CallResponse = Schemas['CallResponse'];\nexport type TransferRequest = Schemas['TransferRequest'];\nexport type IntentsDepositRequest = Schemas['IntentsDepositRequest'];\nexport type IntentsDepositResponse = Schemas['IntentsDepositResponse'];\n\nexport type WithdrawRequest = Schemas['WithdrawRequest'];\nexport type WithdrawResponse = Schemas['WithdrawResponse'];\nexport type DryRunResponse = Schemas['DryRunResponse'];\n\nexport type SwapRequest = Schemas['SwapRequest'];\nexport type SwapResponse = Schemas['SwapResponse'];\nexport type SwapQuoteResponse = Schemas['SwapQuoteResponse'];\n\nexport type SignMessageRequest = Schemas['SignMessageRequest'];\nexport type SignMessageResponse = Schemas['SignMessageResponse'];\n\nexport type RequestStatusResponse = Schemas['RequestStatusResponse'];\nexport type RequestListResponse = Schemas['RequestListResponse'];\n\nexport type PolicyResponse = Schemas['PolicyResponse'];\nexport type PolicyRules = Schemas['PolicyRules'];\nexport type ApprovalConfig = Schemas['ApprovalConfig'];\nexport type EncryptPolicyRequest = Schemas['EncryptPolicyRequest'];\nexport type EncryptPolicyResponse = Schemas['EncryptPolicyResponse'];\nexport type SignPolicyResponse = Schemas['SignPolicyResponse'];\n\nexport type PendingApproval = Schemas['PendingApproval'];\nexport type PendingApprovalsResponse = Schemas['PendingApprovalsResponse'];\nexport type Nep413Auth = Schemas['Nep413Auth'];\nexport type ApproveResponse = Schemas['ApproveResponse'];\n\nexport type AuditEvent = Schemas['AuditEvent'];\nexport type AuditResponse = Schemas['AuditResponse'];\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\ntype Idempotent = { idempotencyKey?: string };\n\nfunction idempotencyHeader(key: string | undefined): Record<string, string> {\n return { 'Idempotency-Key': key ?? newIdempotencyKey() };\n}\n\n// ---------------------------------------------------------------------------\n// Sub-namespaces\n// ---------------------------------------------------------------------------\n\nexport class PolicyAPI {\n constructor(\n private readonly client: FetchClient,\n private readonly retry: Required<RetryConfig>,\n ) {}\n\n get(): Promise<PolicyResponse> {\n return runWithRetry(() => this.client.GET('/wallet/v1/policy'), this.retry);\n }\n\n encrypt(body: EncryptPolicyRequest): Promise<EncryptPolicyResponse> {\n return runWithRetry(() => this.client.POST('/wallet/v1/encrypt-policy', { body }), this.retry);\n }\n\n sign(encryptedData: string): Promise<SignPolicyResponse> {\n return runWithRetry(\n () => this.client.POST('/wallet/v1/sign-policy', { body: { encrypted_data: encryptedData } }),\n this.retry,\n );\n }\n\n invalidateCache(walletId: string): Promise<void> {\n return runWithRetry(\n () => this.client.POST('/wallet/v1/invalidate-cache', { body: { wallet_id: walletId } }),\n this.retry,\n ).then(() => undefined);\n }\n}\n\nexport class ApprovalsAPI {\n constructor(\n private readonly client: FetchClient,\n private readonly retry: Required<RetryConfig>,\n ) {}\n\n listPending(): Promise<PendingApprovalsResponse> {\n return runWithRetry(() => this.client.GET('/wallet/v1/pending_approvals'), this.retry);\n }\n\n approve(approvalId: string, auth: Nep413Auth): Promise<ApproveResponse> {\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/approve/{id}', {\n params: { path: { id: approvalId } },\n body: auth,\n }),\n this.retry,\n );\n }\n\n reject(approvalId: string, auth: Nep413Auth, reason?: string): Promise<ApproveResponse> {\n const body = reason !== undefined ? { ...auth, reason } : auth;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/reject/{id}', {\n params: { path: { id: approvalId } },\n body,\n }),\n this.retry,\n );\n }\n}\n\nexport class AuditAPI {\n constructor(\n private readonly client: FetchClient,\n private readonly retry: Required<RetryConfig>,\n ) {}\n\n list(opts: { limit?: number; offset?: number } = {}): Promise<AuditResponse> {\n return runWithRetry(\n () => this.client.GET('/wallet/v1/audit', { params: { query: opts } }),\n this.retry,\n );\n }\n}\n\n// ---------------------------------------------------------------------------\n// Main client\n// ---------------------------------------------------------------------------\n\nexport class OutlayerClient {\n private readonly client: FetchClient;\n private readonly retry: Required<RetryConfig>;\n\n readonly policy: PolicyAPI;\n readonly approvals: ApprovalsAPI;\n readonly audit: AuditAPI;\n\n constructor(opts: ClientOptions) {\n const { client, retry } = makeClient(opts);\n this.client = client;\n this.retry = retry;\n this.policy = new PolicyAPI(client, retry);\n this.approvals = new ApprovalsAPI(client, retry);\n this.audit = new AuditAPI(client, retry);\n }\n\n // ------- Static factory: register a new wallet (no auth) -------\n\n /**\n * Register a new wallet and obtain an API key.\n *\n * - Empty call: anonymous wallet on OutLayer's shared master. Convenient, no setup.\n * - With `vaultId`: bind to a deployed customer vault so keys derive through\n * the per-vault master. Vault binding is permanent.\n * - With `body`: full control — pass any `RegisterRequest` field (e.g., NEP-413\n * account-binding fields). `vaultId` is merged into `body.vault_id` if not\n * already set.\n *\n * Vault deployment is NOT done here — use the dashboard\n * (https://outlayer.fastnear.com/vault) or `outlayer vault init` CLI.\n * See docs/vaults.md for the full flow.\n */\n static async register(\n opts: {\n vaultId?: string;\n body?: RegisterRequest;\n } & UnauthenticatedOptions = {},\n ): Promise<RegisterResponse> {\n const client = makeUnauthenticatedClient(opts);\n const body: RegisterRequest = { ...(opts.body ?? {}) };\n if (opts.vaultId !== undefined && body.vault_id === undefined) {\n body.vault_id = opts.vaultId;\n }\n const { data, error, response } = await client.POST('/register', { body });\n if (!response.ok) throw await errorFromResponse(response, error);\n return data as RegisterResponse;\n }\n\n // ------- Wallet read -------\n\n getAddress(chain: Chain): Promise<AddressResponse> {\n return runWithRetry(\n () => this.client.GET('/wallet/v1/address', { params: { query: { chain } } }),\n this.retry,\n );\n }\n\n getBalance(\n opts: { chain?: Chain; token?: string; source?: 'chain' | 'intents' } = {},\n ): Promise<BalanceResponse> {\n return runWithRetry(\n () => this.client.GET('/wallet/v1/balance', { params: { query: opts } }),\n this.retry,\n );\n }\n\n listTokens(): Promise<TokensResponse> {\n return runWithRetry(() => this.client.GET('/wallet/v1/tokens'), this.retry);\n }\n\n // ------- Wallet write -------\n\n call(opts: CallRequest & Idempotent): Promise<CallResponse> {\n const { idempotencyKey, ...body } = opts;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/call', {\n body: body as CallRequest,\n headers: idempotencyHeader(idempotencyKey),\n }),\n this.retry,\n );\n }\n\n transfer(opts: TransferRequest & Idempotent): Promise<CallResponse> {\n const { idempotencyKey, ...body } = opts;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/transfer', {\n body: body as TransferRequest,\n headers: idempotencyHeader(idempotencyKey),\n }),\n this.retry,\n );\n }\n\n intentsDeposit(opts: IntentsDepositRequest & Idempotent): Promise<IntentsDepositResponse> {\n const { idempotencyKey, ...body } = opts;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/intents/deposit', {\n body: body as IntentsDepositRequest,\n headers: idempotencyHeader(idempotencyKey),\n }),\n this.retry,\n );\n }\n\n withdraw(opts: WithdrawRequest & Idempotent): Promise<WithdrawResponse> {\n const { idempotencyKey, ...body } = opts;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/intents/withdraw', {\n body: body as WithdrawRequest,\n headers: idempotencyHeader(idempotencyKey),\n }),\n this.retry,\n );\n }\n\n withdrawDryRun(opts: WithdrawRequest): Promise<DryRunResponse> {\n return runWithRetry(\n () => this.client.POST('/wallet/v1/intents/withdraw/dry-run', { body: opts }),\n this.retry,\n );\n }\n\n swap(opts: SwapRequest & Idempotent): Promise<SwapResponse> {\n const { idempotencyKey, ...body } = opts;\n return runWithRetry(\n () =>\n this.client.POST('/wallet/v1/intents/swap', {\n body: body as SwapRequest,\n headers: idempotencyHeader(idempotencyKey),\n }),\n this.retry,\n );\n }\n\n swapQuote(opts: SwapRequest): Promise<SwapQuoteResponse> {\n return runWithRetry(\n () => this.client.POST('/wallet/v1/intents/swap/quote', { body: opts }),\n this.retry,\n );\n }\n\n signMessage(opts: SignMessageRequest): Promise<SignMessageResponse> {\n return runWithRetry(\n () => this.client.POST('/wallet/v1/sign-message', { body: opts }),\n this.retry,\n );\n }\n\n // ------- Async request tracking -------\n\n getRequest(id: string): Promise<RequestStatusResponse> {\n return runWithRetry(\n () => this.client.GET('/wallet/v1/requests/{id}', { params: { path: { id } } }),\n this.retry,\n );\n }\n\n listRequests(\n opts: { type?: RequestType; status?: RequestStatus; limit?: number; offset?: number } = {},\n ): Promise<RequestListResponse> {\n return runWithRetry(\n () => this.client.GET('/wallet/v1/requests', { params: { query: opts } }),\n this.retry,\n );\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@outlayer/sdk",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "TypeScript SDK for OutLayer Agent Custody — multi-chain wallets with TEE-enforced policy.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/out-layer/sdk-js.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://outlayer.fastnear.com/docs/agent-custody",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/out-layer/sdk-js/issues"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"outlayer",
|
|
16
|
+
"near",
|
|
17
|
+
"custody",
|
|
18
|
+
"wallet",
|
|
19
|
+
"tee",
|
|
20
|
+
"agent",
|
|
21
|
+
"ai",
|
|
22
|
+
"policy",
|
|
23
|
+
"multisig"
|
|
24
|
+
],
|
|
25
|
+
"type": "module",
|
|
26
|
+
"main": "./dist/index.cjs",
|
|
27
|
+
"module": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js",
|
|
33
|
+
"require": "./dist/index.cjs"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"spec/openapi.yaml",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"gen": "openapi-typescript spec/openapi.yaml -o src/types.ts",
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"dev": "tsup --watch",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
48
|
+
"lint": "biome check src tests",
|
|
49
|
+
"format": "biome format --write src tests",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"prepublishOnly": "npm run gen && npm run typecheck && npm test && npm run build"
|
|
52
|
+
},
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"openapi-fetch": "^0.13.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@biomejs/biome": "^1.9.4",
|
|
58
|
+
"@types/node": "^22.0.0",
|
|
59
|
+
"msw": "^2.6.0",
|
|
60
|
+
"openapi-typescript": "^7.4.0",
|
|
61
|
+
"tsup": "^8.3.0",
|
|
62
|
+
"typescript": "^5.6.0",
|
|
63
|
+
"vitest": "^2.1.0"
|
|
64
|
+
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=18"
|
|
67
|
+
}
|
|
68
|
+
}
|