@totalis/hip4-client 0.75.0 → 0.76.0
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/CHANGELOG.md +37 -0
- package/dist/generated/openapi.d.ts +2 -2
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/totalis.d.ts +30 -0
- package/dist/totalis.js +59 -9
- package/dist/typed-data.d.ts +31 -1
- package/dist/typed-data.js +24 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,43 @@
|
|
|
3
3
|
`@totalis/hip4-client` follows [semantic versioning](https://semver.org).
|
|
4
4
|
The contract version the generated types come from is `sdkVersion` in `./version`.
|
|
5
5
|
|
|
6
|
+
## 0.76.0
|
|
7
|
+
|
|
8
|
+
Vault agents (TT-2554), one Combo leg per question (TT-2605) and no legs on
|
|
9
|
+
unpriced markets (TT-2606). Generated from contract
|
|
10
|
+
`205.0.0-device-vault-agents`. Additive: 0.75 code runs unchanged, but
|
|
11
|
+
`createRfq` now refuses two legs from one question and legs with a null
|
|
12
|
+
`chance`.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- Vault agents (TT-2554). `agent` in `createTotalis` takes a key the account
|
|
17
|
+
granted; it then signs the account's `TakerAccept`, `SellBack`,
|
|
18
|
+
`CashoutTransfer` and Exits to HyperCore or the account's wallet instead of
|
|
19
|
+
`signer`, so those need no wallet prompt. `signer` still names the account
|
|
20
|
+
and signs USDC authorizations, HyperCore actions, grants and run-off claims.
|
|
21
|
+
- `grantVaultAgent({ agent, validUntil })` has the account sign an
|
|
22
|
+
`AgentGrant` and relays it (`POST /v1/me/vault-agents`); `revokeVaultAgent`
|
|
23
|
+
sends `validUntil` 0, and `vaultAgents()` iterates the live agents.
|
|
24
|
+
- `agentGrantTypedData` in `typed-data`, checked against the vault's vectors.
|
|
25
|
+
- A grant or revoke's default nonce rises past any nonce this client sent
|
|
26
|
+
explicitly for that agent, so it isn't refused for not exceeding it.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- `createRfq` refuses a Combo with two legs from one native question
|
|
31
|
+
(TT-2605): the second such leg is named in `field_violations` as
|
|
32
|
+
`/legs/{i}/outcome_id` with reason `SAME_QUESTION` (`400
|
|
33
|
+
INVALID_REQUEST`). Makers never quoted these legs, so such an RFQ used
|
|
34
|
+
to open and get no quotes. Allow one leg per `native_question_id` in your
|
|
35
|
+
slip; standalone markets have none and always combine.
|
|
36
|
+
- `createRfq` refuses a leg whose market has a side with a null `chance`
|
|
37
|
+
(an empty, dust or one-sided book with no recent evidence), with reason
|
|
38
|
+
`CHANCE_UNAVAILABLE` on `/legs/{i}/outcome_id` (`400 INVALID_REQUEST`).
|
|
39
|
+
Makers price from the book, and on such a book one small order sets the
|
|
40
|
+
price. Show `chance`, not `value`, and treat `chance: null` as unpriced
|
|
41
|
+
(TT-2606).
|
|
42
|
+
|
|
6
43
|
## 0.75.0
|
|
7
44
|
|
|
8
45
|
Maker capital on the stream (TT-2584), a stream that cannot hang in
|
|
@@ -2843,7 +2843,7 @@ export type components = {
|
|
|
2843
2843
|
readonly CreateRfqCommand: {
|
|
2844
2844
|
/** @description Stake in atomic USDC (6 decimals), before taker fees; must be positive. Quotes carry the same stake. */
|
|
2845
2845
|
readonly stake: components["schemas"]["$defs-Amount"];
|
|
2846
|
-
/** @description 1 to 5 legs in strictly increasing outcome_id order. */
|
|
2846
|
+
/** @description 1 to 5 legs in strictly increasing outcome_id order, at most one per native question. Every leg's market must have eligibility ENABLED and combo OPEN, and a chance on each side. */
|
|
2847
2847
|
readonly legs: readonly components["schemas"]["$defs-Leg"][];
|
|
2848
2848
|
/** @description Optional partner attribution code, from any credential. From an account a partner admitted, it must be one of that partner's active codes and needs no signature; with none, the partner's account code is recorded. From any other account it needs builder_authorization_expiry and builder_signature from the partner's registered signer and is honoured only from the code's registered browser origin, so an API-key request (no Origin) from such an account cannot send one. A refused code returns INVALID_REQUEST naming /builder_code. Revocation rejects new RFQs without vetoing an already-created RFQ. Partners get codes from Totalis. */
|
|
2849
2849
|
readonly builder_code?: string;
|
|
@@ -9558,7 +9558,7 @@ export interface operations {
|
|
|
9558
9558
|
readonly "application/json": components["schemas"]["RfqCreated"];
|
|
9559
9559
|
};
|
|
9560
9560
|
};
|
|
9561
|
-
/** @description `INVALID_REQUEST`: the body is malformed, or a leg's market refuses new positions now. A refused leg is named in `field_violations` as `/legs/{i}/outcome_id`, and the message gives the reason, such as `REFERENCE_UNAVAILABLE` or `
|
|
9561
|
+
/** @description `INVALID_REQUEST`: the body is malformed, or a leg's market refuses new positions now. A refused leg is named in `field_violations` as `/legs/{i}/outcome_id`, and the message gives the reason, such as `REFERENCE_UNAVAILABLE`, `OUTSIDE_WINDOW`, `CHANCE_UNAVAILABLE` for a side whose `chance` is null, or `SAME_QUESTION` for a leg whose `native_question_id` an earlier leg already has; the market's `eligibility` and `combo` show when it clears. */
|
|
9562
9562
|
readonly 400: components["responses"]["Error"];
|
|
9563
9563
|
readonly 401: components["responses"]["Error"];
|
|
9564
9564
|
readonly 403: components["responses"]["Error"];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const sdkVersion = "205.0.0-device-vault-agents";
|
|
2
|
-
export declare const openapiSha256 = "
|
|
2
|
+
export declare const openapiSha256 = "93141e0bf50949fc37ebceef7c64555eb50a70f69c71c89c8fdc12780e0dd168";
|
|
3
3
|
export declare const realtimeSha256 = "1cac740e108e84ad1979f6ccc71089efd840404cb72d1612a86edc02769637e3";
|
|
4
4
|
export declare const jsonSchemaSha256: {
|
|
5
5
|
readonly "account.schema.json": "5106e2d53abef190990eff113f6692dd27df5848439cf5a80a42c11e89f2bef6";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Generated by scripts/generate.mjs; do not edit.
|
|
2
2
|
export const sdkVersion = "205.0.0-device-vault-agents";
|
|
3
|
-
export const openapiSha256 = "
|
|
3
|
+
export const openapiSha256 = "93141e0bf50949fc37ebceef7c64555eb50a70f69c71c89c8fdc12780e0dd168";
|
|
4
4
|
export const realtimeSha256 = "1cac740e108e84ad1979f6ccc71089efd840404cb72d1612a86edc02769637e3";
|
|
5
5
|
export const jsonSchemaSha256 = {
|
|
6
6
|
"account.schema.json": "5106e2d53abef190990eff113f6692dd27df5848439cf5a80a42c11e89f2bef6",
|
package/dist/totalis.d.ts
CHANGED
|
@@ -185,6 +185,15 @@ export type TotalisOptions = Omit<ApiClientOptions, "accessToken"> & {
|
|
|
185
185
|
readonly accessToken: AccessToken;
|
|
186
186
|
/** The account's signer (GET /v1/me `wallet`); required for flows that sign. Never stored. */
|
|
187
187
|
readonly signer?: SignerInput;
|
|
188
|
+
/**
|
|
189
|
+
* A key the account granted as a vault agent (`grantVaultAgent`). When set,
|
|
190
|
+
* it signs the account's TakerAccept, SellBack, CashoutTransfer and Exits to
|
|
191
|
+
* its wallet or HyperCore instead of `signer`, so those need no wallet
|
|
192
|
+
* prompt. `signer` still names the account and signs everything else: USDC
|
|
193
|
+
* authorizations, HyperCore actions, grants and run-off claims. The venue
|
|
194
|
+
* refuses an agent whose grant ends before the signed expiry.
|
|
195
|
+
*/
|
|
196
|
+
readonly agent?: SignerInput;
|
|
188
197
|
/** Stream options; `subscription` adds account subscription fields such as `open_rfqs`. */
|
|
189
198
|
readonly stream?: Omit<StreamOptions, "subscription" | "accessToken" | "environment" | "baseUrl" | "streamBaseUrl"> & {
|
|
190
199
|
readonly subscription?: Omit<Extract<StreamSubscription, {
|
|
@@ -638,6 +647,27 @@ export declare function createTotalis(options: TotalisOptions): {
|
|
|
638
647
|
readonly signal?: AbortSignal;
|
|
639
648
|
}) => Promise<CoreExit>;
|
|
640
649
|
directDepositCalls: (amount: Amount) => Promise<readonly WalletCall[]>;
|
|
650
|
+
grantVaultAgent: (request: {
|
|
651
|
+
readonly agent: string;
|
|
652
|
+
readonly validUntil: number | string;
|
|
653
|
+
readonly nonce?: number | string;
|
|
654
|
+
readonly idempotencyKey?: string;
|
|
655
|
+
}) => Promise<{
|
|
656
|
+
readonly operation_id: import("./generated/openapi.js").components["schemas"]["Hash32"];
|
|
657
|
+
}>;
|
|
658
|
+
revokeVaultAgent: (request: {
|
|
659
|
+
readonly agent: string;
|
|
660
|
+
readonly nonce?: number | string;
|
|
661
|
+
readonly idempotencyKey?: string;
|
|
662
|
+
}) => Promise<{
|
|
663
|
+
readonly operation_id: import("./generated/openapi.js").components["schemas"]["Hash32"];
|
|
664
|
+
}>;
|
|
665
|
+
vaultAgents: (limit?: number) => AsyncGenerator<{
|
|
666
|
+
readonly agent: import("./generated/openapi.js").components["schemas"]["Address"];
|
|
667
|
+
readonly valid_until: import("./generated/openapi.js").components["schemas"]["UInt64String"];
|
|
668
|
+
readonly nonce: import("./generated/openapi.js").components["schemas"]["UInt64String"];
|
|
669
|
+
readonly copy_agent: boolean;
|
|
670
|
+
}, void, any>;
|
|
641
671
|
/** Render an RFQ's live quotes (entry or cash-out) from the stream; `[]` while the stream is down. */
|
|
642
672
|
watchQuotes: (rfqId: string, listener: (quotes: readonly Quote[], serverNowMs: number) => void) => () => void;
|
|
643
673
|
/** Issue a personal `ttk_` key; the signer must be the account wallet (embedded, or a wallet-only account's own). */
|
package/dist/totalis.js
CHANGED
|
@@ -7,7 +7,8 @@ import { spendableCash } from "./money.js";
|
|
|
7
7
|
import { ApiError, backoffDelay, envelope, NetworkError, randomBytes32, resendable, retryingFetch, sendOnce, singleFetch, sleep, unwrap, uuidv7 } from "./request.js";
|
|
8
8
|
import { toTotalisSigner } from "./signer.js";
|
|
9
9
|
import { TotalisStream } from "./stream.js";
|
|
10
|
-
import {
|
|
10
|
+
import { items } from "./pagination.js";
|
|
11
|
+
import { address, agentGrantTypedData, cashoutTransferTypedData, exitTypedData, receiveWithAuthorizationTypedData, sellBackTypedData, takerAcceptTypedData, payoutNonce, transferWithAuthorizationTypedData, } from "./typed-data.js";
|
|
11
12
|
/**
|
|
12
13
|
* What an entry's bridge may have moved to its wallet, by its state: nothing
|
|
13
14
|
* before it is sent, once discarded or refused. Only `LANDED` proves it
|
|
@@ -314,7 +315,7 @@ function streamQuotes(stream, read) {
|
|
|
314
315
|
* stream; HTTP reads recover after a reconnect or answer a doorbell.
|
|
315
316
|
*/
|
|
316
317
|
export function createTotalis(options) {
|
|
317
|
-
const { environment, signer: signerInput, stream: streamOptions, streamBaseUrl, accessToken, ...clientOptions } = options;
|
|
318
|
+
const { environment, signer: signerInput, agent: agentInput, stream: streamOptions, streamBaseUrl, accessToken, ...clientOptions } = options;
|
|
318
319
|
const client = audienceClient(environment, { ...clientOptions, accessToken });
|
|
319
320
|
const keys = createApiKeyClient(environment, { ...clientOptions, accessToken });
|
|
320
321
|
const stream = new TotalisStream({
|
|
@@ -337,6 +338,22 @@ export function createTotalis(options) {
|
|
|
337
338
|
};
|
|
338
339
|
const signer = signerInput === undefined ? undefined : toTotalisSigner(signerInput);
|
|
339
340
|
const requireSigner = () => signer ?? Promise.reject(new Error("this flow needs a signer"));
|
|
341
|
+
const agent = agentInput === undefined ? undefined : toTotalisSigner(agentInput);
|
|
342
|
+
// The vault reverts a grant whose nonce does not exceed the agent's last, so
|
|
343
|
+
// two grants for one agent in one second (a grant, then its revoke) must not
|
|
344
|
+
// share one, and a default after an explicit nonce must exceed it too. The
|
|
345
|
+
// vault counts per agent, so the mark is per agent.
|
|
346
|
+
const lastGrantNonce = new Map();
|
|
347
|
+
const grantNonce = (agentAddress, explicit) => {
|
|
348
|
+
const last = lastGrantNonce.get(agentAddress) ?? 0n;
|
|
349
|
+
const clock = BigInt(now());
|
|
350
|
+
const nonce = explicit !== undefined ? BigInt(explicit) : clock > last ? clock : last + 1n;
|
|
351
|
+
if (nonce < 1n || nonce > 2n ** 64n - 1n)
|
|
352
|
+
throw new Error(`grant nonce ${nonce} is outside 1..2^64-1`);
|
|
353
|
+
if (nonce > last)
|
|
354
|
+
lastGrantNonce.set(agentAddress, nonce);
|
|
355
|
+
return String(nonce);
|
|
356
|
+
};
|
|
340
357
|
let deploymentRead;
|
|
341
358
|
const deployment = () => (deploymentRead ??= client.GET("/v1/deployment").then(unwrap).catch((error) => {
|
|
342
359
|
deploymentRead = undefined;
|
|
@@ -585,7 +602,7 @@ export function createTotalis(options) {
|
|
|
585
602
|
const signer = await requireSigner();
|
|
586
603
|
const account = await signer.address();
|
|
587
604
|
const chain = await deployment();
|
|
588
|
-
return { signer, account, chain, scope: { account, chainId: chain.chain_id, vault: address(chain.vault_address.toLowerCase()) } };
|
|
605
|
+
return { signer, vaultSigner: agent ?? signer, account, chain, scope: { account, chainId: chain.chain_id, vault: address(chain.vault_address.toLowerCase()) } };
|
|
589
606
|
}
|
|
590
607
|
/** A stored record signs nothing more, so without a signer the session's wallet (GET /v1/me) stands for the account. */
|
|
591
608
|
async function checkScope(signed) {
|
|
@@ -626,14 +643,14 @@ export function createTotalis(options) {
|
|
|
626
643
|
}
|
|
627
644
|
async function signEntryWith(request, funding) {
|
|
628
645
|
const { quote, cash } = request;
|
|
629
|
-
const { signer, account, chain, scope } = await recordScope();
|
|
646
|
+
const { signer, vaultSigner, account, chain, scope } = await recordScope();
|
|
630
647
|
if (quote.entry.taker.toLowerCase() !== account)
|
|
631
648
|
throw new Error("the quote is for another taker");
|
|
632
649
|
const stake = BigInt(quote.entry.stake);
|
|
633
650
|
const core = request.core === undefined || request.core === null ? request.core : BigInt(request.core);
|
|
634
651
|
// Known cash is planned before any prompt, so a plan that fails asks the wallet for nothing.
|
|
635
652
|
let plan = funding === "plan" && cash !== undefined ? planEntry(stake, core, cash) : undefined;
|
|
636
|
-
const signing =
|
|
653
|
+
const signing = vaultSigner.signTypedData(takerAcceptTypedData(chain, quote.entry));
|
|
637
654
|
if (funding === "plan" && cash === undefined) {
|
|
638
655
|
// The quote signature names no amount, so the wallet signs it while the balances are read; a refusal stops the read and is the call's error.
|
|
639
656
|
const reading = new AbortController();
|
|
@@ -682,12 +699,12 @@ export function createTotalis(options) {
|
|
|
682
699
|
/** Sign a cash-out quote as the position's owner without sending it: the same SellBack or CashoutTransfer digest the maker signs. */
|
|
683
700
|
async function signCashout(request) {
|
|
684
701
|
const { quote } = request;
|
|
685
|
-
const {
|
|
702
|
+
const { vaultSigner, account, chain, scope } = await recordScope();
|
|
686
703
|
const seller = quote.kind === "SELL_BACK" ? quote.sell_back.owner : quote.transfer.seller;
|
|
687
704
|
if (seller.toLowerCase() !== account)
|
|
688
705
|
throw new Error("the quote sells another owner's position");
|
|
689
706
|
const typedData = quote.kind === "SELL_BACK" ? sellBackTypedData(chain, quote.sell_back) : cashoutTransferTypedData(chain, quote.transfer);
|
|
690
|
-
const taker_signature = await
|
|
707
|
+
const taker_signature = await vaultSigner.signTypedData(typedData);
|
|
691
708
|
return {
|
|
692
709
|
kind: "CASHOUT", acceptanceId: request.acceptanceId ?? uuidv7(), rfqId: quote.rfq_id, quoteId: quote.quote_id, ...scope,
|
|
693
710
|
positionId: termsOf(quote).position_id, command: { taker_signature },
|
|
@@ -913,7 +930,7 @@ export function createTotalis(options) {
|
|
|
913
930
|
let vault_withdrawal;
|
|
914
931
|
if (shortfall > 0n) {
|
|
915
932
|
const exit = { amount: shortfall.toString(), expiry: String(issued + 600), salt: BigInt(randomBytes32()).toString() };
|
|
916
|
-
vault_withdrawal = { ...exit, signature: await signer.signTypedData(exitTypedData(chain, { account, to: account, ...exit })) };
|
|
933
|
+
vault_withdrawal = { ...exit, signature: await (agent ?? signer).signTypedData(exitTypedData(chain, { account, to: account, ...exit })) };
|
|
917
934
|
deadline = issued + 600;
|
|
918
935
|
}
|
|
919
936
|
// The venue requires the payout to outlive the vault leg by 300 s; a minute more absorbs clock skew.
|
|
@@ -1065,7 +1082,7 @@ export function createTotalis(options) {
|
|
|
1065
1082
|
const to = address(route.router_address.toLowerCase());
|
|
1066
1083
|
// A minute inside the venue's maximum life absorbs clock skew.
|
|
1067
1084
|
const exit = { amount: BigInt(request.amount).toString(), expiry: String(now() + Math.min(route.maximum_life_seconds - 60, 600)), salt: BigInt(randomBytes32()).toString() };
|
|
1068
|
-
const signature = await signer.signTypedData(exitTypedData(chain, { account, to, ...exit }));
|
|
1085
|
+
const signature = await (agent ?? signer).signTypedData(exitTypedData(chain, { account, to, ...exit }));
|
|
1069
1086
|
const body = envelope({ account, to, ...exit, signature, purpose: request.purpose ?? "ORDER", ...(request.activationFeeAccepted ? { activation_fee_accepted: true } : {}) });
|
|
1070
1087
|
return { exitId, account, body };
|
|
1071
1088
|
}
|
|
@@ -1190,6 +1207,36 @@ export function createTotalis(options) {
|
|
|
1190
1207
|
throw new Error(`core exit ${exitId} ended ${exit.status}, not credited on HyperCore`);
|
|
1191
1208
|
return exit;
|
|
1192
1209
|
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Grant `agent`, a key one of the account's devices holds, as a vault agent
|
|
1212
|
+
* until `validUntil` (unix seconds, at most 180 days away): the account's
|
|
1213
|
+
* `signer` signs the AgentGrant and Totalis relays it to the vault, paying
|
|
1214
|
+
* the gas. Pass that key as `agent` to sign accepts, cash-outs and Exits
|
|
1215
|
+
* back to the account without a wallet prompt. The nonce defaults to the
|
|
1216
|
+
* venue's clock in seconds, and rises past this client's last grant, so a
|
|
1217
|
+
* later grant or revoke supersedes an earlier one. The
|
|
1218
|
+
* 202 is admission: follow `operation_id` with `waitForOperation`; the agent
|
|
1219
|
+
* signs once it lands. A resend of the same `idempotencyKey` returns the
|
|
1220
|
+
* same operation.
|
|
1221
|
+
*/
|
|
1222
|
+
async function grantVaultAgent(request) {
|
|
1223
|
+
const signer = await requireSigner();
|
|
1224
|
+
const account = address((await signer.address()).toLowerCase());
|
|
1225
|
+
const agentAddress = address(request.agent.toLowerCase());
|
|
1226
|
+
const grant = { account, agent: agentAddress, valid_until: String(request.validUntil), nonce: grantNonce(agentAddress, request.nonce) };
|
|
1227
|
+
const signature = await signer.signTypedData(agentGrantTypedData(await deployment(), grant));
|
|
1228
|
+
const key = request.idempotencyKey ?? uuidv7();
|
|
1229
|
+
return sendOnce(() => client.POST("/v1/me/vault-agents", { params: { header: idempotency(key) },
|
|
1230
|
+
body: { agent: grant.agent, valid_until: grant.valid_until, nonce: grant.nonce, signature } }));
|
|
1231
|
+
}
|
|
1232
|
+
/** The agent keeps signing until the revoke's operation lands; `waitForOperation` before treating it as gone. */
|
|
1233
|
+
function revokeVaultAgent(request) {
|
|
1234
|
+
return grantVaultAgent({ ...request, validUntil: 0 });
|
|
1235
|
+
}
|
|
1236
|
+
/** The account's live vault agents, every page; `copy_agent` marks a Combo copy agent's key. */
|
|
1237
|
+
function vaultAgents(limit = 200) {
|
|
1238
|
+
return items((query) => client.GET("/v1/me/vault-agents", { params: { query: { ...query, limit } } }).then(unwrap), (page) => page.agents);
|
|
1239
|
+
}
|
|
1193
1240
|
/**
|
|
1194
1241
|
* The transactions a wallet sends itself to deposit USDC from HyperEVM into
|
|
1195
1242
|
* its vault balance, paying its own gas: approve the vault for `amount`, then
|
|
@@ -1239,6 +1286,9 @@ export function createTotalis(options) {
|
|
|
1239
1286
|
sendReturnToCore,
|
|
1240
1287
|
returnToCore,
|
|
1241
1288
|
directDepositCalls,
|
|
1289
|
+
grantVaultAgent,
|
|
1290
|
+
revokeVaultAgent,
|
|
1291
|
+
vaultAgents,
|
|
1242
1292
|
/** Render an RFQ's live quotes (entry or cash-out) from the stream; `[]` while the stream is down. */
|
|
1243
1293
|
watchQuotes,
|
|
1244
1294
|
/** Issue a personal `ttk_` key; the signer must be the account wallet (embedded, or a wallet-only account's own). */
|
package/dist/typed-data.d.ts
CHANGED
|
@@ -127,15 +127,34 @@ export declare const totalisTypes: {
|
|
|
127
127
|
readonly name: "salt";
|
|
128
128
|
readonly type: "uint256";
|
|
129
129
|
}];
|
|
130
|
+
readonly AgentGrant: readonly [{
|
|
131
|
+
readonly name: "account";
|
|
132
|
+
readonly type: "address";
|
|
133
|
+
}, {
|
|
134
|
+
readonly name: "agent";
|
|
135
|
+
readonly type: "address";
|
|
136
|
+
}, {
|
|
137
|
+
readonly name: "validUntil";
|
|
138
|
+
readonly type: "uint64";
|
|
139
|
+
}, {
|
|
140
|
+
readonly name: "nonce";
|
|
141
|
+
readonly type: "uint64";
|
|
142
|
+
}];
|
|
130
143
|
};
|
|
131
144
|
export type TotalisPrimaryType = Exclude<keyof typeof totalisTypes, "Leg">;
|
|
132
|
-
/**
|
|
145
|
+
/**
|
|
146
|
+
* Who signs each struct: the maker's signer, the taker's signer, or either
|
|
147
|
+
* side of a cash-out. A vault agent the account granted may sign the taker's
|
|
148
|
+
* TakerAccept, SellBack and CashoutTransfer, and an Exit back to the account;
|
|
149
|
+
* only the account itself signs an AgentGrant.
|
|
150
|
+
*/
|
|
133
151
|
export declare const signedBy: {
|
|
134
152
|
readonly Quote: "maker";
|
|
135
153
|
readonly TakerAccept: "taker";
|
|
136
154
|
readonly SellBack: "maker_and_taker";
|
|
137
155
|
readonly CashoutTransfer: "maker_and_taker";
|
|
138
156
|
readonly Exit: "taker";
|
|
157
|
+
readonly AgentGrant: "taker";
|
|
139
158
|
};
|
|
140
159
|
/** The vault deployment a signature binds to: GET /v1/deployment. */
|
|
141
160
|
export type TotalisDeployment = Pick<Schemas["Deployment"], "chain_id" | "vault_address">;
|
|
@@ -201,6 +220,17 @@ export declare function exitTypedData(deployment: TotalisDeployment, exit: {
|
|
|
201
220
|
expiry: string;
|
|
202
221
|
salt: string;
|
|
203
222
|
}): TotalisTypedData<"Exit">;
|
|
223
|
+
/**
|
|
224
|
+
* The account's grant to a vault agent: a key it holds signs for the account
|
|
225
|
+
* until `valid_until` (unix seconds, at most 180 days away; 0 revokes). The
|
|
226
|
+
* nonce must exceed the agent's last grant. Relay it with POST /v1/me/vault-agents.
|
|
227
|
+
*/
|
|
228
|
+
export declare function agentGrantTypedData(deployment: TotalisDeployment, grant: {
|
|
229
|
+
account: Hex;
|
|
230
|
+
agent: Hex;
|
|
231
|
+
valid_until: string;
|
|
232
|
+
nonce: string;
|
|
233
|
+
}): TotalisTypedData<"AgentGrant">;
|
|
204
234
|
export declare const domainTypes: {
|
|
205
235
|
readonly EIP712Domain: readonly [{
|
|
206
236
|
readonly name: "name";
|
package/dist/typed-data.js
CHANGED
|
@@ -47,14 +47,26 @@ export const totalisTypes = {
|
|
|
47
47
|
{ name: "expiry", type: "uint64" },
|
|
48
48
|
{ name: "salt", type: "uint256" },
|
|
49
49
|
],
|
|
50
|
+
AgentGrant: [
|
|
51
|
+
{ name: "account", type: "address" },
|
|
52
|
+
{ name: "agent", type: "address" },
|
|
53
|
+
{ name: "validUntil", type: "uint64" },
|
|
54
|
+
{ name: "nonce", type: "uint64" },
|
|
55
|
+
],
|
|
50
56
|
};
|
|
51
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* Who signs each struct: the maker's signer, the taker's signer, or either
|
|
59
|
+
* side of a cash-out. A vault agent the account granted may sign the taker's
|
|
60
|
+
* TakerAccept, SellBack and CashoutTransfer, and an Exit back to the account;
|
|
61
|
+
* only the account itself signs an AgentGrant.
|
|
62
|
+
*/
|
|
52
63
|
export const signedBy = {
|
|
53
64
|
Quote: "maker",
|
|
54
65
|
TakerAccept: "taker",
|
|
55
66
|
SellBack: "maker_and_taker",
|
|
56
67
|
CashoutTransfer: "maker_and_taker",
|
|
57
68
|
Exit: "taker",
|
|
69
|
+
AgentGrant: "taker",
|
|
58
70
|
};
|
|
59
71
|
/** A 20-byte hex address, or a TypeError. */
|
|
60
72
|
export function address(value) {
|
|
@@ -122,6 +134,17 @@ export function exitTypedData(deployment, exit) {
|
|
|
122
134
|
message: { account: exit.account, to: exit.to, amount: BigInt(exit.amount), expiry: BigInt(exit.expiry), salt: BigInt(exit.salt) },
|
|
123
135
|
};
|
|
124
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* The account's grant to a vault agent: a key it holds signs for the account
|
|
139
|
+
* until `valid_until` (unix seconds, at most 180 days away; 0 revokes). The
|
|
140
|
+
* nonce must exceed the agent's last grant. Relay it with POST /v1/me/vault-agents.
|
|
141
|
+
*/
|
|
142
|
+
export function agentGrantTypedData(deployment, grant) {
|
|
143
|
+
return {
|
|
144
|
+
domain: domain(deployment), types: { AgentGrant: totalisTypes.AgentGrant }, primaryType: "AgentGrant",
|
|
145
|
+
message: { account: address(grant.account), agent: address(grant.agent), validUntil: BigInt(grant.valid_until), nonce: BigInt(grant.nonce) },
|
|
146
|
+
};
|
|
147
|
+
}
|
|
125
148
|
// ---------------------------------------------------------------------------
|
|
126
149
|
// EIP-712 hashing, so makers can compute quote_digest and every signer can be
|
|
127
150
|
// checked against the contract's vectors without a wallet library.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@totalis/hip4-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.76.0",
|
|
4
4
|
"description": "Totalis HIP-4 SDK: typed HTTP clients, signer-agnostic typed data, a retrying request layer, pagination, a realtime stream and taker/maker flows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|