northstar-eva-sdk 0.6.0 → 0.7.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/README.md +1 -0
- package/dist/northstar-eva-sdk.d.ts +56 -0
- package/dist/northstar-eva-sdk.js +63 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,6 +36,7 @@ const sdk = NorthstarEva.create({ provider, erRpc: "https://ephemeral.devnet.son
|
|
|
36
36
|
- **`l1Endpoint`** means "the provider's RPC is the ER; this is the L1." It's the cleanest fit when your app's provider already points at the ER. (`L1Endpoint` is accepted too.)
|
|
37
37
|
- **Same SDK, both services:** with no `l1Endpoint`/`erRpc`, you get a normal eva client — one codebase covers the NorthStar and non-NorthStar deployments.
|
|
38
38
|
- **Withdraw returns to the sender:** `withdrawFeeFromEr({ lamports })` reclaims the fee to whoever funded the ER (the SDK signer) — no recipient needed.
|
|
39
|
+
- **Session helpers:** `await sdk.isSessionOpen()` (read-only boolean), `await sdk.getSession()` (decoded session struct — validator, `ttlSlots`, `createdAt`, `expiresAtSlot`, … or `null`), and `await sdk.buildEnsureSessionIx()` (returns the OpenSession instruction to compose/sign yourself, or `null` if the session already exists).
|
|
39
40
|
|
|
40
41
|
## What's new in 0.4.0
|
|
41
42
|
|
|
@@ -101,6 +101,46 @@ export interface GlobalState {
|
|
|
101
101
|
tradingDuration: bigint;
|
|
102
102
|
}
|
|
103
103
|
export declare function decodeGlobalState(data: Uint8Array): GlobalState;
|
|
104
|
+
export declare const SESSION_LEN = 219;
|
|
105
|
+
export declare const SESSION_DISCRIMINATOR = 1;
|
|
106
|
+
export declare const SESSION_OFFSETS: {
|
|
107
|
+
readonly discriminator: 0;
|
|
108
|
+
readonly gridId: 1;
|
|
109
|
+
readonly ttlSlots: 9;
|
|
110
|
+
readonly feeCap: 17;
|
|
111
|
+
readonly createdAt: 25;
|
|
112
|
+
readonly nonce: 33;
|
|
113
|
+
readonly authority: 49;
|
|
114
|
+
readonly validator: 81;
|
|
115
|
+
readonly settlementIntervalSlots: 113;
|
|
116
|
+
readonly lastSettledL1Slot: 121;
|
|
117
|
+
readonly lastSettledErSlot: 129;
|
|
118
|
+
readonly settlementStatus: 137;
|
|
119
|
+
readonly settlementErSlot: 138;
|
|
120
|
+
readonly settlementStartedL1Slot: 210;
|
|
121
|
+
readonly bump: 218;
|
|
122
|
+
};
|
|
123
|
+
export type SettlementStatus = "Idle" | "InProgress" | "Unknown";
|
|
124
|
+
export interface SessionAccount {
|
|
125
|
+
discriminator: number;
|
|
126
|
+
gridId: bigint;
|
|
127
|
+
ttlSlots: bigint;
|
|
128
|
+
feeCap: bigint;
|
|
129
|
+
createdAt: bigint;
|
|
130
|
+
/** created_at + ttl_slots — the session is expired once the L1 slot passes this (matches the program's `is_expired`). */
|
|
131
|
+
expiresAtSlot: bigint;
|
|
132
|
+
nonce: bigint;
|
|
133
|
+
authority: Uint8Array;
|
|
134
|
+
validator: Uint8Array;
|
|
135
|
+
settlementIntervalSlots: bigint;
|
|
136
|
+
lastSettledL1Slot: bigint;
|
|
137
|
+
lastSettledErSlot: bigint;
|
|
138
|
+
settlementStatus: SettlementStatus;
|
|
139
|
+
settlementErSlot: bigint;
|
|
140
|
+
settlementStartedL1Slot: bigint;
|
|
141
|
+
bump: number;
|
|
142
|
+
}
|
|
143
|
+
export declare function decodeSession(data: Uint8Array): SessionAccount;
|
|
104
144
|
export declare function decodeTokenAmount(data: Uint8Array): bigint;
|
|
105
145
|
/**
|
|
106
146
|
* Network presets + resolved config. Works for localnet now and devnet later —
|
|
@@ -319,6 +359,15 @@ export declare class NorthstarEva {
|
|
|
319
359
|
getSessionPdaFromEr(): Promise<any>;
|
|
320
360
|
getDelegatedAccounts(): Promise<string[]>;
|
|
321
361
|
sessionPda(): anchor.web3.PublicKey;
|
|
362
|
+
/**
|
|
363
|
+
* Read + decode the Portal session account from L1 (the single global session for this Portal).
|
|
364
|
+
* Returns `null` if no valid session exists. Read-only — no transaction, no fee. Use the returned
|
|
365
|
+
* `ttlSlots`/`createdAt`/`expiresAtSlot`/`validator` for details (compare `expiresAtSlot` to the
|
|
366
|
+
* current L1 slot — `await this.l1.getSlot()` — to tell if it's expired).
|
|
367
|
+
*/
|
|
368
|
+
getSession(): Promise<SessionAccount | null>;
|
|
369
|
+
/** True if a valid Portal session is open on L1 (read-only; no tx). */
|
|
370
|
+
isSessionOpen(): Promise<boolean>;
|
|
322
371
|
/** Sign `tx` with a mixed set of signers: raw Keypairs are partial-signed, wallet adapters sign via signTransaction. */
|
|
323
372
|
private signTx;
|
|
324
373
|
private sendOnL1;
|
|
@@ -333,6 +382,13 @@ export declare class NorthstarEva {
|
|
|
333
382
|
buildOpenSessionIx(): TransactionInstruction;
|
|
334
383
|
/** Portal CloseSession instruction (L1). */
|
|
335
384
|
buildCloseSessionIx(): TransactionInstruction;
|
|
385
|
+
/**
|
|
386
|
+
* Build version of {@link ensureSession}: returns the OpenSession instruction **only if the
|
|
387
|
+
* session isn't created yet**, or **`null`** if it already exists. Async (it reads the session
|
|
388
|
+
* on L1). The caller composes the returned ix into a tx, signs, and submits — e.g.:
|
|
389
|
+
* `const ix = await sdk.buildEnsureSessionIx(); if (ix) tx.add(ix);`
|
|
390
|
+
*/
|
|
391
|
+
buildEnsureSessionIx(): Promise<TransactionInstruction | null>;
|
|
336
392
|
/** Portal DepositFee instruction (L1) — "fund fee to ER payer". (Caller must ensure a session exists.) */
|
|
337
393
|
buildDepositFeeIx(lamports: bigint, recipient?: PublicKey): TransactionInstruction;
|
|
338
394
|
/** "Withdraw fee from ER" instruction (ER) — system transfer from `sender` (default: the signer) → its WithdrawalSink. (Portal SOL bridge; distinct from the eva `withdraw` instruction.) */
|
|
@@ -1938,6 +1938,41 @@ export function decodeGlobalState(data) {
|
|
|
1938
1938
|
tradingDuration: data.length >= 96 ? uLE(data, 88, 8) : 0n,
|
|
1939
1939
|
};
|
|
1940
1940
|
}
|
|
1941
|
+
// ---- Portal Session (portal/src/state.rs struct Session; Borsh, LEN 219, discriminator 1) ----
|
|
1942
|
+
export const SESSION_LEN = 219;
|
|
1943
|
+
export const SESSION_DISCRIMINATOR = 1;
|
|
1944
|
+
export const SESSION_OFFSETS = {
|
|
1945
|
+
discriminator: 0, gridId: 1, ttlSlots: 9, feeCap: 17, createdAt: 25, nonce: 33,
|
|
1946
|
+
authority: 49, validator: 81, settlementIntervalSlots: 113, lastSettledL1Slot: 121,
|
|
1947
|
+
lastSettledErSlot: 129, settlementStatus: 137, settlementErSlot: 138,
|
|
1948
|
+
settlementStartedL1Slot: 210, bump: 218,
|
|
1949
|
+
};
|
|
1950
|
+
const SETTLEMENT_STATUS = ["Idle", "InProgress"];
|
|
1951
|
+
export function decodeSession(data) {
|
|
1952
|
+
if (data.length < SESSION_LEN)
|
|
1953
|
+
throw new Error(`Session data too short: ${data.length} < ${SESSION_LEN}`);
|
|
1954
|
+
const o = SESSION_OFFSETS;
|
|
1955
|
+
const createdAt = uLE(data, o.createdAt, 8);
|
|
1956
|
+
const ttlSlots = uLE(data, o.ttlSlots, 8);
|
|
1957
|
+
return {
|
|
1958
|
+
discriminator: data[o.discriminator],
|
|
1959
|
+
gridId: uLE(data, o.gridId, 8),
|
|
1960
|
+
ttlSlots,
|
|
1961
|
+
feeCap: uLE(data, o.feeCap, 8),
|
|
1962
|
+
createdAt,
|
|
1963
|
+
expiresAtSlot: createdAt + ttlSlots,
|
|
1964
|
+
nonce: uLE(data, o.nonce, 16),
|
|
1965
|
+
authority: data.slice(o.authority, o.authority + 32),
|
|
1966
|
+
validator: data.slice(o.validator, o.validator + 32),
|
|
1967
|
+
settlementIntervalSlots: uLE(data, o.settlementIntervalSlots, 8),
|
|
1968
|
+
lastSettledL1Slot: uLE(data, o.lastSettledL1Slot, 8),
|
|
1969
|
+
lastSettledErSlot: uLE(data, o.lastSettledErSlot, 8),
|
|
1970
|
+
settlementStatus: SETTLEMENT_STATUS[data[o.settlementStatus]] ?? "Unknown",
|
|
1971
|
+
settlementErSlot: uLE(data, o.settlementErSlot, 8),
|
|
1972
|
+
settlementStartedL1Slot: uLE(data, o.settlementStartedL1Slot, 8),
|
|
1973
|
+
bump: data[o.bump],
|
|
1974
|
+
};
|
|
1975
|
+
}
|
|
1941
1976
|
// ---- SPL token account amount (u64 @ 64) ----
|
|
1942
1977
|
export function decodeTokenAmount(data) {
|
|
1943
1978
|
if (data.length < 72)
|
|
@@ -2321,6 +2356,22 @@ export class NorthstarEva {
|
|
|
2321
2356
|
getSessionPdaFromEr() { return this.erRpc("getSessionPda"); }
|
|
2322
2357
|
getDelegatedAccounts() { return this.erRpc("getDelegatedAccounts"); }
|
|
2323
2358
|
sessionPda() { return portal.sessionPda(this.cfg.portalProgramId); }
|
|
2359
|
+
/**
|
|
2360
|
+
* Read + decode the Portal session account from L1 (the single global session for this Portal).
|
|
2361
|
+
* Returns `null` if no valid session exists. Read-only — no transaction, no fee. Use the returned
|
|
2362
|
+
* `ttlSlots`/`createdAt`/`expiresAtSlot`/`validator` for details (compare `expiresAtSlot` to the
|
|
2363
|
+
* current L1 slot — `await this.l1.getSlot()` — to tell if it's expired).
|
|
2364
|
+
*/
|
|
2365
|
+
async getSession() {
|
|
2366
|
+
const info = await this.l1GetAccount(this.sessionPda());
|
|
2367
|
+
if (!info || info.data.length < SESSION_LEN || info.data[0] !== SESSION_DISCRIMINATOR)
|
|
2368
|
+
return null;
|
|
2369
|
+
return decodeSession(info.data);
|
|
2370
|
+
}
|
|
2371
|
+
/** True if a valid Portal session is open on L1 (read-only; no tx). */
|
|
2372
|
+
async isSessionOpen() {
|
|
2373
|
+
return (await this.getSession()) !== null;
|
|
2374
|
+
}
|
|
2324
2375
|
// ───────────────────────── signing (adapter-based, no Keypair required) ─────────────────────────
|
|
2325
2376
|
/** Sign `tx` with a mixed set of signers: raw Keypairs are partial-signed, wallet adapters sign via signTransaction. */
|
|
2326
2377
|
async signTx(tx, signers) {
|
|
@@ -2415,6 +2466,18 @@ export class NorthstarEva {
|
|
|
2415
2466
|
buildCloseSessionIx() {
|
|
2416
2467
|
return portal.closeSessionIx({ programId: this.cfg.portalProgramId, closer: this.payer });
|
|
2417
2468
|
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Build version of {@link ensureSession}: returns the OpenSession instruction **only if the
|
|
2471
|
+
* session isn't created yet**, or **`null`** if it already exists. Async (it reads the session
|
|
2472
|
+
* on L1). The caller composes the returned ix into a tx, signs, and submits — e.g.:
|
|
2473
|
+
* `const ix = await sdk.buildEnsureSessionIx(); if (ix) tx.add(ix);`
|
|
2474
|
+
*/
|
|
2475
|
+
async buildEnsureSessionIx() {
|
|
2476
|
+
this.requireNorthStar("buildEnsureSessionIx");
|
|
2477
|
+
if (await this.l1GetAccount(this.sessionPda()))
|
|
2478
|
+
return null; // already created
|
|
2479
|
+
return this.buildOpenSessionIx();
|
|
2480
|
+
}
|
|
2418
2481
|
/** Portal DepositFee instruction (L1) — "fund fee to ER payer". (Caller must ensure a session exists.) */
|
|
2419
2482
|
buildDepositFeeIx(lamports, recipient = this.payer) {
|
|
2420
2483
|
return portal.depositFeeIx({ programId: this.cfg.portalProgramId, depositor: this.payer, recipient, lamports });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "northstar-eva-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Run the eva program on a NorthStar ephemeral rollup (zero-fee hot path). A high-level class SDK over the NorthStar Portal/ER protocol + the eva Anchor program. Works localnet & devnet.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|