@mida-context/sdk 0.1.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/LICENSE +21 -0
- package/README.md +26 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +7115 -0
- package/dist/types/api/app.d.ts +99 -0
- package/dist/types/api/auth-pure.d.ts +51 -0
- package/dist/types/api/auth.d.ts +17 -0
- package/dist/types/api/authorize.d.ts +24 -0
- package/dist/types/api/batch-deny.d.ts +22 -0
- package/dist/types/api/batch-routes.d.ts +69 -0
- package/dist/types/api/batch-store.d.ts +96 -0
- package/dist/types/api/batcher.d.ts +220 -0
- package/dist/types/api/browser.d.ts +14 -0
- package/dist/types/api/chain-budget.d.ts +61 -0
- package/dist/types/api/chain-views.d.ts +87 -0
- package/dist/types/api/client.d.ts +295 -0
- package/dist/types/api/deny-overlay.d.ts +81 -0
- package/dist/types/api/errors.d.ts +30 -0
- package/dist/types/api/file-stores.d.ts +7 -0
- package/dist/types/api/index.d.ts +17 -0
- package/dist/types/api/secure-fs.d.ts +12 -0
- package/dist/types/api/store.d.ts +51 -0
- package/dist/types/api/stores.d.ts +171 -0
- package/dist/types/api/verify-assertion.d.ts +22 -0
- package/dist/types/api/wire.d.ts +27 -0
- package/dist/types/chain/abis.d.ts +2125 -0
- package/dist/types/chain/browser.d.ts +20 -0
- package/dist/types/chain/deployment-fs.d.ts +15 -0
- package/dist/types/chain/deployment.d.ts +33 -0
- package/dist/types/chain/deployments.generated.d.ts +1 -0
- package/dist/types/chain/gas.d.ts +47 -0
- package/dist/types/chain/history.d.ts +52 -0
- package/dist/types/chain/index.d.ts +13 -0
- package/dist/types/chain/local.d.ts +34 -0
- package/dist/types/chain/logs.d.ts +62 -0
- package/dist/types/chain/placements.d.ts +92 -0
- package/dist/types/chain/read-scope.d.ts +66 -0
- package/dist/types/chain/registry.d.ts +16 -0
- package/dist/types/chain/sponsored.d.ts +93 -0
- package/dist/types/chain/transport.d.ts +53 -0
- package/dist/types/chain/writes.d.ts +165 -0
- package/dist/types/crypto/aead.d.ts +5 -0
- package/dist/types/crypto/bytes.d.ts +4 -0
- package/dist/types/crypto/derive.d.ts +20 -0
- package/dist/types/crypto/index.d.ts +6 -0
- package/dist/types/crypto/object.d.ts +42 -0
- package/dist/types/crypto/payload.d.ts +21 -0
- package/dist/types/crypto/wraps.d.ts +36 -0
- package/dist/types/grant-advisor/advise.d.ts +23 -0
- package/dist/types/grant-advisor/authority.d.ts +44 -0
- package/dist/types/grant-advisor/index.d.ts +5 -0
- package/dist/types/grant-advisor/manifest.d.ts +66 -0
- package/dist/types/grant-advisor/policy.d.ts +91 -0
- package/dist/types/grant-advisor/signatures.d.ts +10 -0
- package/dist/types/mida-context-sdk/daemon.d.ts +27 -0
- package/dist/types/mida-context-sdk/errors.d.ts +27 -0
- package/dist/types/mida-context-sdk/index.d.ts +5 -0
- package/dist/types/mida-context-sdk/local.d.ts +40 -0
- package/dist/types/mida-context-sdk/mida.d.ts +65 -0
- package/dist/types/mida-context-sdk/transport.d.ts +137 -0
- package/dist/types/protocol/batch.d.ts +161 -0
- package/dist/types/protocol/constants.d.ts +56 -0
- package/dist/types/protocol/errors.d.ts +15 -0
- package/dist/types/protocol/ids.d.ts +72 -0
- package/dist/types/protocol/index.d.ts +11 -0
- package/dist/types/protocol/namespaces.d.ts +15 -0
- package/dist/types/protocol/owner-link.d.ts +146 -0
- package/dist/types/protocol/typed-data.d.ts +365 -0
- package/dist/types/protocol/types.d.ts +215 -0
- package/dist/types/protocol/webauthn-assertion.d.ts +29 -0
- package/dist/types/protocol/wire.d.ts +8 -0
- package/dist/types/sdk/agent.d.ts +279 -0
- package/dist/types/sdk/batched.d.ts +68 -0
- package/dist/types/sdk/connect.d.ts +88 -0
- package/dist/types/sdk/index.d.ts +7 -0
- package/dist/types/sdk/request-store.d.ts +26 -0
- package/dist/types/storage/index.d.ts +23 -0
- package/package.json +50 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import type { Address, Hex } from "../protocol/index.js";
|
|
2
|
+
import type { Abi, Account, LocalAccount, TransactionReceipt, WalletClient } from "viem";
|
|
3
|
+
import type { Deployment } from "./deployment.js";
|
|
4
|
+
import type { TxKind } from "./gas.js";
|
|
5
|
+
import type { ChainContext } from "./registry.js";
|
|
6
|
+
import type { SponsoredSender } from "./sponsored.js";
|
|
7
|
+
/**
|
|
8
|
+
* The fee fields a send carries — the answer of `estimateFeesPerGas`, forwarded verbatim into
|
|
9
|
+
* the transaction so the number the balance guard checked is the number the node checks (R5-9).
|
|
10
|
+
* An EIP-1559 chain sets `maxFeePerGas`/`maxPriorityFeePerGas`; a legacy chain sets `gasPrice`.
|
|
11
|
+
*/
|
|
12
|
+
export interface SendFee {
|
|
13
|
+
maxFeePerGas?: bigint;
|
|
14
|
+
maxPriorityFeePerGas?: bigint;
|
|
15
|
+
gasPrice?: bigint;
|
|
16
|
+
}
|
|
17
|
+
/** What a send is about to cost the payer, handed to `beforeSend` after the estimates. */
|
|
18
|
+
export interface SendCost {
|
|
19
|
+
payer: Address;
|
|
20
|
+
gasLimit: bigint;
|
|
21
|
+
/**
|
|
22
|
+
* The exact fee values the transaction goes out with. The node verifies the payer against
|
|
23
|
+
* `gasLimit × maxFeePerGas` — checking a fresh (cheaper) gas price instead let a wallet
|
|
24
|
+
* through that the send itself then refused (R5-9).
|
|
25
|
+
*/
|
|
26
|
+
fee: SendFee;
|
|
27
|
+
/** A plain transfer's moved value — part of the payer's total exposure, absent on contract calls. */
|
|
28
|
+
value?: bigint;
|
|
29
|
+
/**
|
|
30
|
+
* Set when `gasLimit` is a bound, not a measured estimate: the node's own `eth_estimateGas`
|
|
31
|
+
* refused to run, so the send was priced at the kind's ceiling. A balance guard phrases the
|
|
32
|
+
* refusal "needs up to X MON" rather than claiming a precision the bound does not have (M3-D6).
|
|
33
|
+
*/
|
|
34
|
+
upperBound?: boolean;
|
|
35
|
+
}
|
|
36
|
+
export interface WriteContext extends ChainContext {
|
|
37
|
+
walletClient: WalletClient;
|
|
38
|
+
account: Account;
|
|
39
|
+
/**
|
|
40
|
+
* Runs between the gas estimate and the send: the payer's balance can be checked against the
|
|
41
|
+
* estimated cost and topped up, or the send refused before a transaction the wallet cannot
|
|
42
|
+
* pay for goes out (R4-4). Only the owner's context wires this; agent signers keep the bare
|
|
43
|
+
* node error, exactly as before. On the sponsored path it never runs — the user pays nothing.
|
|
44
|
+
* The `gate` it is handed is THIS send's abandonment gate: a guard that sends a transaction
|
|
45
|
+
* of its own (an owner top-up) must pass it down, so the nested send stops too when the
|
|
46
|
+
* outer send's cap already fired (in-18 S4).
|
|
47
|
+
*/
|
|
48
|
+
beforeSend?: (cost: SendCost, gate: SendGate) => Promise<void>;
|
|
49
|
+
/**
|
|
50
|
+
* When set, `sendContract` asks this sender to pay the gas first (the user still signs; the
|
|
51
|
+
* sponsor pays). A SponsorDidNotPay falls back to the self-paid path — or refuses, when
|
|
52
|
+
* SPONSOR_FALLBACK_TO_SELF_PAY is off. Any other error (an included-but-reverted operation
|
|
53
|
+
* among them) propagates untouched: the sponsor did pay and the call itself failed.
|
|
54
|
+
*/
|
|
55
|
+
sponsor?: SponsoredSender;
|
|
56
|
+
/**
|
|
57
|
+
* One plain line while a slow step runs — where the sponsor fallback explains itself. Wired by
|
|
58
|
+
* the runtime to its own progress channel; unset means silent code paths stay silent.
|
|
59
|
+
*/
|
|
60
|
+
progress?: (line: string) => void;
|
|
61
|
+
/**
|
|
62
|
+
* The bounded wait every send runs under (in-15 J-4): while the chain stays silent a
|
|
63
|
+
* "still waiting for Monad (N s)…" line ticks on `progress` every `everyMs`, and once `capMs`
|
|
64
|
+
* passes the send throws SEND_TIMEOUT — the error says whether a transaction hash exists, so
|
|
65
|
+
* "sent but unconfirmed" and "nothing left the process" are never the same line. Timer
|
|
66
|
+
* callbacks are injectable so a test runs the clock; defaults below.
|
|
67
|
+
*/
|
|
68
|
+
sendWatch?: {
|
|
69
|
+
everyMs?: number;
|
|
70
|
+
capMs?: number;
|
|
71
|
+
setTimeout?: (fn: () => void, ms: number) => unknown;
|
|
72
|
+
clearTimeout?: (timer: unknown) => void;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
/** A write context whose account can sign typed data locally (operators, owners and agent signers in tests and the CLI). */
|
|
76
|
+
export interface LocalWriteContext extends WriteContext {
|
|
77
|
+
account: LocalAccount;
|
|
78
|
+
}
|
|
79
|
+
export declare function createWriteContext(input: {
|
|
80
|
+
rpcUrl: string;
|
|
81
|
+
deployment: Deployment;
|
|
82
|
+
account: LocalAccount;
|
|
83
|
+
}): LocalWriteContext;
|
|
84
|
+
/** A mined receipt plus the gas limit the transaction was actually sent with — the number Monad bills. */
|
|
85
|
+
export type SentReceipt = TransactionReceipt & {
|
|
86
|
+
gasLimit: bigint;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* `sent === false` on a thrown error marks a failure from BEFORE any transaction left the
|
|
90
|
+
* process — simulation, gas estimation, the fee estimate, the balance guard. A caller that
|
|
91
|
+
* requeues work on failure (the batcher) reads it here to tell "nothing was sent", a plain
|
|
92
|
+
* size or availability signal that is safe to resubmit, from "the send's answer was lost",
|
|
93
|
+
* where the transaction may already have landed. A failure thrown after `writeContract` —
|
|
94
|
+
* including the sponsor's own send, whose operation may still be in flight — is never marked.
|
|
95
|
+
*/
|
|
96
|
+
export declare function failedBeforeSend(error: unknown): boolean;
|
|
97
|
+
/** A "still waiting for Monad" line ticks this often while a send is in flight (in-15 J-4). */
|
|
98
|
+
export declare const SEND_PROGRESS_EVERY_MS = 15000;
|
|
99
|
+
/** The most a send waits on Monad before reporting what it honestly knows (in-15 J-4). */
|
|
100
|
+
export declare const SEND_CAP_MS = 120000;
|
|
101
|
+
/**
|
|
102
|
+
* The gate a send checks in the same synchronous stretch as every broadcast point — once the
|
|
103
|
+
* watchdog's cap has fired, a slow pre-send step (a simulate, an estimate, a top-up's own
|
|
104
|
+
* receipt wait) resolving late must not turn the refusal the caller already saw into a real
|
|
105
|
+
* send (in-16 K-1). The check and the send call sit back to back so no timer can run between
|
|
106
|
+
* them; after it throws, the abandoned work promise unwinds without broadcasting.
|
|
107
|
+
*/
|
|
108
|
+
export interface SendGate {
|
|
109
|
+
checkAbandoned(): void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Whether a sponsor failure falls back to paying gas from the user's own wallet. The testnet
|
|
113
|
+
* probe's step f (docs/evidence/m3-sponsor-probe.json, Sep 21) measured that a 7702-delegated
|
|
114
|
+
* address holding under 10 MON CAN still pay its own gas, so the fallback is safe — the
|
|
115
|
+
* reviewer flips this constant if a later probe or a Monad change breaks that finding, and the
|
|
116
|
+
* fallback message becomes a refusal with instructions instead.
|
|
117
|
+
*/
|
|
118
|
+
export declare const SPONSOR_FALLBACK_TO_SELF_PAY = true;
|
|
119
|
+
/**
|
|
120
|
+
* Simulates first so a revert surfaces as a named contract error mapped to a protocol code. The
|
|
121
|
+
* simulate is an `eth_call` carrying no gas field — it runs from a wallet holding nothing, which
|
|
122
|
+
* is exactly why it may stay on the sponsored path (M3-D3). With a sponsor set the sponsor is
|
|
123
|
+
* asked next, with NO owner-side `estimateContractGas`: that estimate is `eth_estimateGas` with
|
|
124
|
+
* the owner as sender, which Monad refuses for a wallet that cannot afford the worst case — the
|
|
125
|
+
* very wallet a sponsor exists for. The bundler estimates the operation instead, and the kind's
|
|
126
|
+
* ceiling is checked inside the sponsored sender against the bundler's own `callGasLimit`.
|
|
127
|
+
*
|
|
128
|
+
* Only the self-paid path — no sponsor, or a sponsor that refused before accepting — runs the
|
|
129
|
+
* estimate, the ceiling check and the balance guard: the send is refused above the kind's
|
|
130
|
+
* ceiling (Monad bills the limit, not the usage), and within it goes out with `gas` set
|
|
131
|
+
* explicitly to the estimate — no padding. A receipt with status "reverted" (for example a
|
|
132
|
+
* Monad reserve-balance revert after inclusion) is an error, never a silent success.
|
|
133
|
+
*/
|
|
134
|
+
export declare function sendContract(context: WriteContext, call: {
|
|
135
|
+
address: Address;
|
|
136
|
+
abi: Abi;
|
|
137
|
+
functionName: string;
|
|
138
|
+
args: readonly unknown[];
|
|
139
|
+
}, kind: TxKind,
|
|
140
|
+
/** A nested send inherits the outer send's abandonment through this — see watchSend. */
|
|
141
|
+
outerGate?: SendGate): Promise<SentReceipt>;
|
|
142
|
+
/**
|
|
143
|
+
* A plain value transfer under the same ceiling rule: the node's estimate is the explicit `gas`
|
|
144
|
+
* on the send, refused above the kind's ceiling. Used for environment funding (R3-1).
|
|
145
|
+
*/
|
|
146
|
+
export declare function sendValue(context: WriteContext, transfer: {
|
|
147
|
+
to: Address;
|
|
148
|
+
value: bigint;
|
|
149
|
+
}, kind: TxKind,
|
|
150
|
+
/** A nested send inherits the outer send's abandonment through this — see watchSend. */
|
|
151
|
+
outerGate?: SendGate): Promise<SentReceipt>;
|
|
152
|
+
/**
|
|
153
|
+
* Operator-side agent registration (§4.3). The proposed signer signs MidaAgentRegistrationV1 over every field;
|
|
154
|
+
* the contract fixes encryptionKeyVersion and capabilityManifestVersion at 1.
|
|
155
|
+
*/
|
|
156
|
+
export declare function registerAgent(context: WriteContext, input: {
|
|
157
|
+
agentSalt: Hex;
|
|
158
|
+
signer: LocalAccount;
|
|
159
|
+
encryptionPublicKey: Hex;
|
|
160
|
+
callbackOrigin: string;
|
|
161
|
+
capabilityManifestHash: Hex;
|
|
162
|
+
}): Promise<{
|
|
163
|
+
agentId: Hex;
|
|
164
|
+
receipt: TransactionReceipt;
|
|
165
|
+
}>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const KEY_BYTES = 32;
|
|
2
|
+
export declare const NONCE_BYTES = 24;
|
|
3
|
+
export declare const TAG_BYTES = 16;
|
|
4
|
+
export declare function seal(key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
|
|
5
|
+
export declare function open(key: Uint8Array, nonce: Uint8Array, aad: Uint8Array, ciphertext: Uint8Array): Uint8Array;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Hex, IsolationDomain } from "../protocol/index.js";
|
|
2
|
+
export declare const ISOLATION_DOMAINS: readonly IsolationDomain[];
|
|
3
|
+
/** §6.1: SHA256(UTF8("mida/context/prf/<domain>/v1")). */
|
|
4
|
+
export declare function prfSalt(domain: IsolationDomain): Uint8Array;
|
|
5
|
+
/** §6.2: HKDF-SHA256(ikm = PRF_D, salt = namespaceId, info, 32). */
|
|
6
|
+
export declare function deriveNamespaceSecret(domainPrfOutput: Uint8Array, namespaceId: Hex): Uint8Array;
|
|
7
|
+
export declare function uint64be(value: bigint): Uint8Array;
|
|
8
|
+
export interface X25519KeyPair {
|
|
9
|
+
privateKey: Uint8Array;
|
|
10
|
+
publicKey: Uint8Array;
|
|
11
|
+
}
|
|
12
|
+
export interface EpochKeyPair extends X25519KeyPair {
|
|
13
|
+
readEpoch: bigint;
|
|
14
|
+
}
|
|
15
|
+
/** §7.1: epochSeed = HKDF-SHA256(namespaceSecret, uint64be(readEpoch), info, 32); noble clamps the scalar. */
|
|
16
|
+
export declare function deriveEpochKeyPair(namespaceSecret: Uint8Array, readEpoch: bigint): EpochKeyPair;
|
|
17
|
+
export declare function x25519PublicKey(privateKey: Uint8Array): Uint8Array;
|
|
18
|
+
export declare function generateX25519KeyPair(): X25519KeyPair;
|
|
19
|
+
/** §7.1: reject an all-zero public key or shared secret before any HKDF. */
|
|
20
|
+
export declare function x25519SharedSecret(privateKey: Uint8Array, publicKey: Uint8Array): Uint8Array;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ContextPayload, EpochDEKWrap, Hex, ObjectManifest } from "../protocol/index.js";
|
|
2
|
+
import type { ObjectBinding } from "./payload.js";
|
|
3
|
+
/** §9.1: ciphertextHash = SHA256(ciphertextBytes). */
|
|
4
|
+
export declare function ciphertextHash(ciphertext: Uint8Array): Hex;
|
|
5
|
+
/** §9.1: manifestHash = keccak256(RFC 8785 canonical manifest bytes). */
|
|
6
|
+
export declare function manifestHash(manifest: ObjectManifest): Hex;
|
|
7
|
+
export declare function buildObjectManifest(input: {
|
|
8
|
+
contextId: Hex;
|
|
9
|
+
ciphertext: Uint8Array;
|
|
10
|
+
payloadNonce: Uint8Array;
|
|
11
|
+
readEpoch: bigint;
|
|
12
|
+
epochDekWrap: EpochDEKWrap;
|
|
13
|
+
}): ObjectManifest;
|
|
14
|
+
/**
|
|
15
|
+
* Checks, in order: the manifest matches its on-chain commitment, its embedded wrap belongs to the same
|
|
16
|
+
* object and epoch, and the ciphertext bytes match the committed hash and size. Runs before any decryption.
|
|
17
|
+
*/
|
|
18
|
+
export declare function verifyObjectManifest(input: {
|
|
19
|
+
manifest: ObjectManifest;
|
|
20
|
+
expectedManifestHash: Hex;
|
|
21
|
+
ciphertext: Uint8Array;
|
|
22
|
+
}): void;
|
|
23
|
+
export interface SealedContextObject {
|
|
24
|
+
ciphertext: Uint8Array;
|
|
25
|
+
manifest: ObjectManifest;
|
|
26
|
+
manifestHash: Hex;
|
|
27
|
+
ciphertextCommitment: Hex;
|
|
28
|
+
}
|
|
29
|
+
/** Encrypts a payload and wraps its DEK to the epoch public key. Needs only the public key (§7.1 CREATE). */
|
|
30
|
+
export declare function sealContextObject(input: {
|
|
31
|
+
payload: ContextPayload;
|
|
32
|
+
binding: ObjectBinding;
|
|
33
|
+
epochPublicKey: Uint8Array;
|
|
34
|
+
}): SealedContextObject;
|
|
35
|
+
/** Verifies commitments, unwraps the DEK with the epoch private key, and decrypts (§7.1 READ). */
|
|
36
|
+
export declare function openContextObject(input: {
|
|
37
|
+
manifest: ObjectManifest;
|
|
38
|
+
expectedManifestHash: Hex;
|
|
39
|
+
ciphertext: Uint8Array;
|
|
40
|
+
epochPrivateKey: Uint8Array;
|
|
41
|
+
binding: ObjectBinding;
|
|
42
|
+
}): ContextPayload;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Address, ContextPayload, Hex } from "../protocol/index.js";
|
|
2
|
+
/** Values every object-level AAD binds (§8.2, §8.3). */
|
|
3
|
+
export interface ObjectBinding {
|
|
4
|
+
chainId: bigint;
|
|
5
|
+
contextRegistry: Address;
|
|
6
|
+
contextId: Hex;
|
|
7
|
+
namespaceId: Hex;
|
|
8
|
+
readEpoch: bigint;
|
|
9
|
+
}
|
|
10
|
+
export declare function payloadAad(binding: ObjectBinding): Uint8Array;
|
|
11
|
+
export declare function epochDekWrapAad(binding: ObjectBinding): Uint8Array;
|
|
12
|
+
export declare function encodePayload(payload: ContextPayload): Uint8Array;
|
|
13
|
+
export declare function decodePayload(bytes: Uint8Array): ContextPayload;
|
|
14
|
+
export interface EncryptedPayload {
|
|
15
|
+
ciphertext: Uint8Array;
|
|
16
|
+
nonce: Uint8Array;
|
|
17
|
+
dek: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
/** §8.2: fresh random DEK and nonce for every object. */
|
|
20
|
+
export declare function encryptPayload(payload: ContextPayload, binding: ObjectBinding): EncryptedPayload;
|
|
21
|
+
export declare function decryptPayload(encrypted: EncryptedPayload, binding: ObjectBinding): ContextPayload;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Address, EpochDEKWrap, Hex, ReaderEpochWrap } from "../protocol/index.js";
|
|
2
|
+
import type { ObjectBinding } from "./payload.js";
|
|
3
|
+
/** §8.3: wrap an object DEK to the namespace epoch public key. */
|
|
4
|
+
export declare function wrapDekToEpoch(input: {
|
|
5
|
+
dek: Uint8Array;
|
|
6
|
+
epochPublicKey: Uint8Array;
|
|
7
|
+
binding: ObjectBinding;
|
|
8
|
+
}): EpochDEKWrap;
|
|
9
|
+
export declare function unwrapDekFromEpoch(input: {
|
|
10
|
+
wrap: EpochDEKWrap;
|
|
11
|
+
epochPrivateKey: Uint8Array;
|
|
12
|
+
binding: ObjectBinding;
|
|
13
|
+
}): Uint8Array;
|
|
14
|
+
/** Values the reader-wrap AAD binds (§8.4). */
|
|
15
|
+
export interface ReaderBinding {
|
|
16
|
+
chainId: bigint;
|
|
17
|
+
capabilityRegistry: Address;
|
|
18
|
+
owner: Address;
|
|
19
|
+
namespaceId: Hex;
|
|
20
|
+
readEpoch: bigint;
|
|
21
|
+
agentId: Hex;
|
|
22
|
+
agentKeyVersion: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function readerEpochWrapAad(binding: ReaderBinding): Uint8Array;
|
|
25
|
+
/** §8.4: wrap an epoch private key to one agent's registered X25519 key and version. */
|
|
26
|
+
export declare function wrapEpochPrivateKeyToAgent(input: {
|
|
27
|
+
epochPrivateKey: Uint8Array;
|
|
28
|
+
agentEncryptionPublicKey: Uint8Array;
|
|
29
|
+
binding: ReaderBinding;
|
|
30
|
+
createdAt: bigint;
|
|
31
|
+
}): ReaderEpochWrap;
|
|
32
|
+
export declare function unwrapEpochPrivateKey(input: {
|
|
33
|
+
wrap: ReaderEpochWrap;
|
|
34
|
+
agentEncryptionPrivateKey: Uint8Array;
|
|
35
|
+
binding: ReaderBinding;
|
|
36
|
+
}): Uint8Array;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AccessRequest, AgentRecord, GrantAdvice, OwnerAgentHistory, SignedAgentCapabilityManifest } from "../protocol/index.js";
|
|
2
|
+
/** §14.5. There is deliberately no field for model output, explanations or reputation. */
|
|
3
|
+
export interface GrantAdvisorInput {
|
|
4
|
+
request: AccessRequest;
|
|
5
|
+
manifest: SignedAgentCapabilityManifest;
|
|
6
|
+
agentRecord: AgentRecord;
|
|
7
|
+
ownerHistory: OwnerAgentHistory;
|
|
8
|
+
now: bigint;
|
|
9
|
+
}
|
|
10
|
+
export declare const MAX_REQUEST_WINDOW_SECONDS = 600n;
|
|
11
|
+
/**
|
|
12
|
+
* The request's own validity window. It needs only the request and the chain's clock — one
|
|
13
|
+
* getBlock — so callers check it BEFORE paying for the agent-record and owner-history reads the
|
|
14
|
+
* full advisor needs: an expired request refuses cheaply, with the same REQUEST_EXPIRED the
|
|
15
|
+
* full check below would throw (in-15 J-2). assertRequestIsCurrent calls this too, so nothing
|
|
16
|
+
* that reaches the signature checks escapes it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function assertRequestFresh(request: AccessRequest, now: bigint): void;
|
|
19
|
+
/**
|
|
20
|
+
* §14.5 deterministic Grant Advisor. Pure and synchronous: identical input gives identical output.
|
|
21
|
+
* The recommendation is always a subset of the signed request; the function throws rather than return one that is not.
|
|
22
|
+
*/
|
|
23
|
+
export declare function adviseGrant(input: GrantAdvisorInput): GrantAdvice;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AccessGrantResponse, AccessRequest, EffectiveAuthority, GrantScope, RequestedScope } from "../protocol/index.js";
|
|
2
|
+
export declare const HIGH_FINAL_SELECTION_CAP_SECONDS: bigint;
|
|
3
|
+
/** Builder-facing scope: a namespace string (parent allowed) plus permission and provenance bits. */
|
|
4
|
+
export interface ScopeInput {
|
|
5
|
+
namespace: string;
|
|
6
|
+
permissions: number;
|
|
7
|
+
provenancePolicy?: number;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* §5.3: canonicalize every namespace, expand parents through frozen tree v1, merge bits per exact
|
|
11
|
+
* namespace, and return sorted canonical scopes. This is the only way builder input becomes signed authority.
|
|
12
|
+
*/
|
|
13
|
+
export declare function expandScopeInputs(inputs: readonly ScopeInput[]): RequestedScope[];
|
|
14
|
+
/**
|
|
15
|
+
* §14.5 exact authority tuples: one per (namespace, permission), plus one per (namespace, permission, provenance policy).
|
|
16
|
+
* Tuple containment is equivalent to per-namespace bit containment; a property test proves it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function effectiveAuthority(scopes: readonly RequestedScope[]): EffectiveAuthority[];
|
|
19
|
+
export declare const authorityKey: (tuple: EffectiveAuthority) => string;
|
|
20
|
+
export declare function isAuthoritySubset(candidate: readonly EffectiveAuthority[], requested: readonly EffectiveAuthority[]): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Same rule the contract enforces in grantBatch: every candidate namespace is requested, with no extra bits.
|
|
23
|
+
* Out-of-range bit values on either side fail the bound check before any bitwise operator runs.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isScopeSubset(candidate: readonly RequestedScope[], requested: readonly RequestedScope[]): boolean;
|
|
26
|
+
/** A shorter expiry is narrower. Requested 0 means unbounded, so any value fits; a finite request never becomes unbounded. */
|
|
27
|
+
export declare function isExpiryWithin(candidate: bigint, requested: bigint): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* The user's final choice (§14.5, §14.4, §10.4 rule 7). Used by FakeVault before signing and by the SDK on completion.
|
|
30
|
+
* The user may pick ELEVATED or undeclared authority, but never anything outside the signed request.
|
|
31
|
+
*/
|
|
32
|
+
export declare function assertFinalSelection(input: {
|
|
33
|
+
requestedScopes: readonly RequestedScope[];
|
|
34
|
+
requestedExpiresAt: bigint;
|
|
35
|
+
finalScopes: readonly GrantScope[];
|
|
36
|
+
finalExpiresAt: bigint;
|
|
37
|
+
now: bigint;
|
|
38
|
+
}): void;
|
|
39
|
+
/**
|
|
40
|
+
* §13.3 off-chain half of completeAccessRequest: the response must echo the original request and grant only a
|
|
41
|
+
* subset of it with one expiry. Returns the sorted final scopes. The SDK must still prove each capability exists
|
|
42
|
+
* and is currently valid on Monad (Task 25); this function never reads the chain.
|
|
43
|
+
*/
|
|
44
|
+
export declare function assertGrantResponseWithinRequest(request: AccessRequest, response: AccessGrantResponse, now: bigint): GrantScope[];
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { AgentCapabilityManifestBody, AgentRecord, Address, Hex, SignedAgentCapabilityManifest } from "../protocol/index.js";
|
|
2
|
+
export declare const MANIFEST_LIMITS: Readonly<{
|
|
3
|
+
nameBytes: 80;
|
|
4
|
+
textBytes: 280;
|
|
5
|
+
purposes: 8;
|
|
6
|
+
scopeDeclarations: 32;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function normalizeManifestBody(body: AgentCapabilityManifestBody): AgentCapabilityManifestBody;
|
|
9
|
+
/** Enforces every §14.1 structural rule and limit on the NFC-normalized body. Sensitivity claims are rejected as unknown keys. */
|
|
10
|
+
export declare function validateManifestBody(input: unknown, now: bigint): asserts input is AgentCapabilityManifestBody;
|
|
11
|
+
export declare function manifestBodyHash(body: AgentCapabilityManifestBody): Hex;
|
|
12
|
+
export declare function manifestEnvelopeBytes(envelope: SignedAgentCapabilityManifest): Uint8Array;
|
|
13
|
+
export declare function manifestEnvelopeHash(envelope: SignedAgentCapabilityManifest): Hex;
|
|
14
|
+
export declare function manifestBindingFor(input: {
|
|
15
|
+
chainId: bigint;
|
|
16
|
+
capabilityRegistry: Address;
|
|
17
|
+
body: AgentCapabilityManifestBody;
|
|
18
|
+
}): {
|
|
19
|
+
domain: {
|
|
20
|
+
name: string;
|
|
21
|
+
version: string;
|
|
22
|
+
chainId: bigint;
|
|
23
|
+
verifyingContract: `0x${string}`;
|
|
24
|
+
};
|
|
25
|
+
types: {
|
|
26
|
+
readonly ManifestBinding: readonly [{
|
|
27
|
+
readonly name: "bodyHash";
|
|
28
|
+
readonly type: "bytes32";
|
|
29
|
+
}, {
|
|
30
|
+
readonly name: "agentId";
|
|
31
|
+
readonly type: "bytes32";
|
|
32
|
+
}, {
|
|
33
|
+
readonly name: "manifestVersion";
|
|
34
|
+
readonly type: "uint64";
|
|
35
|
+
}];
|
|
36
|
+
};
|
|
37
|
+
primaryType: "ManifestBinding";
|
|
38
|
+
message: {
|
|
39
|
+
bodyHash: `0x${string}`;
|
|
40
|
+
agentId: `0x${string}`;
|
|
41
|
+
manifestVersion: bigint;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* §14.1 currentness check. Order: structure, agent identity, version, body hash, operator signature.
|
|
46
|
+
* An envelope is current only when its body hash and version equal the on-chain AgentRecord.
|
|
47
|
+
*/
|
|
48
|
+
export declare function verifySignedManifest(input: {
|
|
49
|
+
envelope: SignedAgentCapabilityManifest;
|
|
50
|
+
agentRecord: AgentRecord;
|
|
51
|
+
chainId: bigint;
|
|
52
|
+
capabilityRegistry: Address;
|
|
53
|
+
now: bigint;
|
|
54
|
+
}): {
|
|
55
|
+
bodyHash: Hex;
|
|
56
|
+
envelopeHash: Hex;
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* For GET /agent-manifests/:bodyHash (§14.1): stored bytes must hash to the indexed envelope hash, be canonical,
|
|
60
|
+
* and contain a body whose hash is the requested body hash. The signature is checked later by verifySignedManifest.
|
|
61
|
+
*/
|
|
62
|
+
export declare function parseManifestEnvelopeBytes(input: {
|
|
63
|
+
bytes: Uint8Array;
|
|
64
|
+
expectedEnvelopeHash: Hex;
|
|
65
|
+
expectedBodyHash: Hex;
|
|
66
|
+
}): SignedAgentCapabilityManifest;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { Hex, Permission, ProvenancePolicy, PurposeId } from "../protocol/index.js";
|
|
2
|
+
export type Sensitivity = "LOW" | "MEDIUM" | "HIGH";
|
|
3
|
+
export type Classification = "EXPECTED" | "ELEVATED" | "SUSPICIOUS" | "UNCLASSIFIED";
|
|
4
|
+
export interface PolicyEntry {
|
|
5
|
+
readonly namespace: string;
|
|
6
|
+
readonly permissions: readonly Permission[];
|
|
7
|
+
readonly provenancePolicies: readonly ProvenancePolicy[];
|
|
8
|
+
}
|
|
9
|
+
export interface PurposePolicy {
|
|
10
|
+
readonly expected: readonly PolicyEntry[];
|
|
11
|
+
readonly elevated: readonly PolicyEntry[];
|
|
12
|
+
readonly suspicious: "ALL_HIGH";
|
|
13
|
+
}
|
|
14
|
+
export interface PurposeRule {
|
|
15
|
+
classification: Classification;
|
|
16
|
+
permissions: number;
|
|
17
|
+
provenancePolicy: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The canonical policy document for mida-grant-policy-v1 (§14.2–§14.4).
|
|
21
|
+
* Its RFC 8785 keccak256 hash is POLICY_HASH_V1, which Solidity mirrors as a constant (Task 14).
|
|
22
|
+
* Changing any byte here is a new policy version, never an edit.
|
|
23
|
+
*/
|
|
24
|
+
export declare const POLICY_DOCUMENT_V1: {
|
|
25
|
+
readonly v: 1;
|
|
26
|
+
readonly policyVersion: "mida-grant-policy-v1";
|
|
27
|
+
readonly namespaceTreeVersion: "mida-namespace-tree-v1";
|
|
28
|
+
readonly sensitivity: {
|
|
29
|
+
readonly LOW: readonly ["preferences", "preferences.communication", "preferences.tools", "preferences.work", "profile.skills", "projects.current"];
|
|
30
|
+
readonly MEDIUM: readonly ["profile", "profile.identity", "goals", "goals.career", "goals.learning", "goals.personal", "projects", "projects.past", "decisions", "decisions.career", "decisions.projects", "relationships"];
|
|
31
|
+
readonly HIGH: readonly ["credentials", "financial", "financial.preferences", "private"];
|
|
32
|
+
};
|
|
33
|
+
readonly consent: {
|
|
34
|
+
readonly LOW: "normal_approval";
|
|
35
|
+
readonly MEDIUM: "explicit_justification";
|
|
36
|
+
readonly HIGH: "warning_and_individual_selection";
|
|
37
|
+
};
|
|
38
|
+
readonly durationCapsSeconds: {
|
|
39
|
+
readonly LOW: 2592000;
|
|
40
|
+
readonly MEDIUM: 604800;
|
|
41
|
+
readonly HIGH: 86400;
|
|
42
|
+
};
|
|
43
|
+
readonly purposes: {
|
|
44
|
+
career_coaching: {
|
|
45
|
+
expected: PolicyEntry[];
|
|
46
|
+
elevated: PolicyEntry[];
|
|
47
|
+
suspicious: "ALL_HIGH";
|
|
48
|
+
};
|
|
49
|
+
general_assistance: {
|
|
50
|
+
expected: PolicyEntry[];
|
|
51
|
+
elevated: PolicyEntry[];
|
|
52
|
+
suspicious: "ALL_HIGH";
|
|
53
|
+
};
|
|
54
|
+
project_assistance: {
|
|
55
|
+
expected: PolicyEntry[];
|
|
56
|
+
elevated: PolicyEntry[];
|
|
57
|
+
suspicious: "ALL_HIGH";
|
|
58
|
+
};
|
|
59
|
+
travel_planning: {
|
|
60
|
+
expected: PolicyEntry[];
|
|
61
|
+
elevated: PolicyEntry[];
|
|
62
|
+
suspicious: "ALL_HIGH";
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
readonly rules: {
|
|
66
|
+
readonly neverDefault: readonly ["ELEVATED", "SUSPICIOUS", "UNCLASSIFIED", "UNDECLARED", "HIGH", "SUPERSEDE_ANY"];
|
|
67
|
+
readonly elevatedProvenancePolicies: readonly ["ALLOW_IMPORTED", "ALLOW_EXTERNAL_ATTESTATION"];
|
|
68
|
+
readonly inferenceRequiresManifestAndPurpose: true;
|
|
69
|
+
readonly provenanceRequiresWritePermission: true;
|
|
70
|
+
readonly broadParentScopeWarning: true;
|
|
71
|
+
readonly highFinalSelectionCapSeconds: 86400;
|
|
72
|
+
readonly singleExpiryPerBatch: true;
|
|
73
|
+
readonly selectAllExcludesHigh: true;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
export declare const POLICY_HASH_V1: Hex;
|
|
77
|
+
export declare const PURPOSE_IDS: readonly PurposeId[];
|
|
78
|
+
export declare const DURATION_CAP_SECONDS: Readonly<Record<Sensitivity, bigint>>;
|
|
79
|
+
export declare const ELEVATED_PROVENANCE_BITS: number;
|
|
80
|
+
export declare const WRITE_PERMISSION_BITS: number;
|
|
81
|
+
export declare function isPurposeId(value: string): value is PurposeId;
|
|
82
|
+
export declare function stricterSensitivity(a: Sensitivity, b: Sensitivity): Sensitivity;
|
|
83
|
+
/** A namespace's effective sensitivity is at least that of everything it expands to (§14.2). */
|
|
84
|
+
export declare function sensitivityOf(namespace: string): Sensitivity;
|
|
85
|
+
export declare function sensitivityOfId(namespaceId: Hex): Sensitivity;
|
|
86
|
+
export declare function permissionBits(names: readonly Permission[]): number;
|
|
87
|
+
export declare function provenancePolicyBits(names: readonly ProvenancePolicy[]): number;
|
|
88
|
+
export declare function permissionNames(bits: number): Permission[];
|
|
89
|
+
export declare function provenancePolicyNames(bits: number): ProvenancePolicy[];
|
|
90
|
+
/** Exact (purpose, namespace) classification under §14.3. HIGH is always SUSPICIOUS. */
|
|
91
|
+
export declare function classifyScope(purposeId: PurposeId, namespaceId: Hex): PurposeRule;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AccessRequest, Address, Hex } from "../protocol/index.js";
|
|
2
|
+
import type { TypedDataDefinition } from "viem";
|
|
3
|
+
/**
|
|
4
|
+
* Synchronous EIP-712 signer recovery. viem's verifyTypedData is async, but adviseGrant is a pure
|
|
5
|
+
* synchronous function (§14.5), so recovery uses viem's hashTypedData plus ox's secp256k1 recovery.
|
|
6
|
+
* Tests cross-check the result against viem's verifyTypedData. EOA signers only; ERC-1271 is not supported.
|
|
7
|
+
*/
|
|
8
|
+
export declare function recoverTypedDataSigner(typedData: TypedDataDefinition, signature: Hex): Address | null;
|
|
9
|
+
export declare function isTypedDataSignedBy(typedData: TypedDataDefinition, signature: Hex, expected: Address): boolean;
|
|
10
|
+
export declare function assertAccessRequestSignature(request: AccessRequest, signer: Address): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the Mida home lives for this SDK: the `home` option, then `$MIDA_HOME` (absolute, like
|
|
3
|
+
* the CLI insists), then `~/.mida`. The SDK never creates the folder — a home that does not
|
|
4
|
+
* exist simply means the service is not running.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveMidaHome(home: string | undefined, env?: Record<string, string | undefined>): string;
|
|
7
|
+
/**
|
|
8
|
+
* The same socket path the daemon computes: `<home>/midad.sock`, a pointer file
|
|
9
|
+
* (`midad.sock.path`) winning when present, and the per-user fallback folder
|
|
10
|
+
* `<base>/mida-<uid>/mida-<16 hex of sha256(home)>.sock` when the direct path is too long.
|
|
11
|
+
* Must stay byte-for-byte equivalent to control.ts's `socketPathFor` — the daemon writes the
|
|
12
|
+
* pointer for exactly the cases the computed path would miss.
|
|
13
|
+
*/
|
|
14
|
+
export declare function socketPathFor(home: string, base?: string): string;
|
|
15
|
+
export interface DaemonReply {
|
|
16
|
+
/** 0 means no answer — no socket, refused connection, timeout, or a non-JSON body. */
|
|
17
|
+
status: number;
|
|
18
|
+
body: unknown;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One JSON call to the daemon over the private socket. Never throws and never hangs: any failure
|
|
22
|
+
* resolves to status 0, and the caller turns that into `service-unavailable`. A body of
|
|
23
|
+
* `undefined` sends GET; anything else is POSTed as JSON.
|
|
24
|
+
*/
|
|
25
|
+
export declare function callDaemon(home: string, path: string, body: unknown, options: {
|
|
26
|
+
timeoutMs: number;
|
|
27
|
+
}): Promise<DaemonReply>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every failure an SDK call can raise carries one of these codes. The SDK's own codes say why the
|
|
3
|
+
* call never left this machine (or never could); the rest are the Mida service's refusal reasons,
|
|
4
|
+
* passed through unchanged so a caller can key on exactly what the daemon said.
|
|
5
|
+
*/
|
|
6
|
+
export type MidaSdkErrorCode = "transport-unavailable" | "invalid-option" | "service-unavailable" | "service-refused" | "failed" | "bad-agent" | "bad-input" | "no-identity" | "identity-unreadable" | "general-assistance" | "not-a-project" | "folder-mismatch" | "list-tampered" | "list-unreadable" | "check-failed" | "already-approved" | "not-approved" | "revoked" | "revoke-pending" | "read-only" | "rate-limited" | "invalid-shape" | "invalid-content" | "invalid-namespace" | "too-large" | "not-found" | "partial-read" | "chain-busy" | "chain-misconfigured" | "rpc-auth" | "store-misconfigured" | "store-rpc-auth";
|
|
7
|
+
/**
|
|
8
|
+
* The one error the SDK throws. `code` names the failure class; the message is one plain sentence
|
|
9
|
+
* that says what did NOT happen — no provider URL, key or raw upstream message ever reaches it.
|
|
10
|
+
*/
|
|
11
|
+
export declare class MidaSdkError extends Error {
|
|
12
|
+
readonly code: MidaSdkErrorCode;
|
|
13
|
+
/** The service's own refusal reason — present only when it is not the code itself. */
|
|
14
|
+
readonly serviceReason?: string;
|
|
15
|
+
/** Which save lane a `rate-limited` refusal names — set only on that code. */
|
|
16
|
+
readonly lane?: "direct" | "batched";
|
|
17
|
+
constructor(code: MidaSdkErrorCode, message: string, options?: {
|
|
18
|
+
cause?: unknown;
|
|
19
|
+
serviceReason?: string;
|
|
20
|
+
lane?: "direct" | "batched";
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
/** Maps the service's refusal reason onto an SDK code — verbatim when known, `service-refused` when not. */
|
|
24
|
+
export declare function serviceRefusal(reason: string, text: string, options?: {
|
|
25
|
+
lane?: "direct" | "batched";
|
|
26
|
+
}): MidaSdkError;
|
|
27
|
+
export declare function isMidaSdkError(error: unknown, code?: MidaSdkErrorCode): error is MidaSdkError;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { Mida } from "./mida.js";
|
|
2
|
+
export type { MidaOptions, TransportKind } from "./mida.js";
|
|
3
|
+
export { MidaSdkError, isMidaSdkError, serviceRefusal } from "./errors.js";
|
|
4
|
+
export type { MidaSdkErrorCode } from "./errors.js";
|
|
5
|
+
export type { ContextInput, ContextItem, ContextResult, HandoffAnswer, RememberInput, RememberResult, RequestAccessResult, StatusAnswer, Transport, VerifyCheck, VerifyResult, WhatsNewAnswer, } from "./transport.js";
|