@opendatalabs/vana-sdk 3.15.0 → 3.17.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 +107 -0
- package/dist/errors.cjs +94 -2
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +123 -0
- package/dist/errors.js +82 -1
- package/dist/errors.js.map +1 -1
- package/dist/index.browser.d.ts +4 -0
- package/dist/index.browser.js +1155 -14
- package/dist/index.browser.js.map +4 -4
- package/dist/index.node.cjs +1205 -15
- package/dist/index.node.cjs.map +4 -4
- package/dist/index.node.d.ts +4 -0
- package/dist/index.node.js +1155 -14
- package/dist/index.node.js.map +4 -4
- package/dist/protocol/gateway.cjs +16 -2
- package/dist/protocol/gateway.cjs.map +1 -1
- package/dist/protocol/gateway.d.ts +2 -0
- package/dist/protocol/gateway.js +16 -2
- package/dist/protocol/gateway.js.map +1 -1
- package/dist/protocol/lineage.cjs +287 -0
- package/dist/protocol/lineage.cjs.map +1 -0
- package/dist/protocol/lineage.d.ts +228 -0
- package/dist/protocol/lineage.js +258 -0
- package/dist/protocol/lineage.js.map +1 -0
- package/dist/protocol/lineage.test.d.ts +1 -0
- package/dist/protocol/personal-server-error-body.cjs +57 -0
- package/dist/protocol/personal-server-error-body.cjs.map +1 -0
- package/dist/protocol/personal-server-error-body.d.ts +18 -0
- package/dist/protocol/personal-server-error-body.js +32 -0
- package/dist/protocol/personal-server-error-body.js.map +1 -0
- package/dist/protocol/personal-server-write.cjs +623 -0
- package/dist/protocol/personal-server-write.cjs.map +1 -0
- package/dist/protocol/personal-server-write.d.ts +284 -0
- package/dist/protocol/personal-server-write.js +601 -0
- package/dist/protocol/personal-server-write.js.map +1 -0
- package/dist/protocol/personal-server-write.test.d.ts +1 -0
- package/dist/protocol/scope-actions.cjs +185 -0
- package/dist/protocol/scope-actions.cjs.map +1 -0
- package/dist/protocol/scope-actions.d.ts +145 -0
- package/dist/protocol/scope-actions.js +154 -0
- package/dist/protocol/scope-actions.js.map +1 -0
- package/dist/protocol/scope-actions.test.d.ts +1 -0
- package/dist/protocol/write-signer.cjs +67 -0
- package/dist/protocol/write-signer.cjs.map +1 -0
- package/dist/protocol/write-signer.d.ts +59 -0
- package/dist/protocol/write-signer.js +43 -0
- package/dist/protocol/write-signer.js.map +1 -0
- package/dist/protocol/write-signer.test.d.ts +1 -0
- package/dist/tests/mock-personal-server.d.ts +127 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/scope-actions.ts"],"sourcesContent":["import { scopeMatchesPattern } from \"./scopes\";\n\n/**\n * Grant scope-entry grammar.\n *\n * A signed grant carries `scopes: string[]`. Each entry is\n * `[operation:]scope` - an optional lowercase ASCII operation prefix before\n * the first `:`, then a scope pattern (`*`, `{prefix}.*`, or an exact scope).\n * A missing prefix means read. `write:notes.entries` authorizes writing\n * `notes.entries` and nothing else; `notes.entries` authorizes reading it.\n *\n * The string form is the wire and storage detail: it is what the grantor\n * signs (EIP-712 `GrantRegistration.scopes`) and what the gateway stores\n * verbatim. The Personal Server is the sole interpreter, and this module is\n * the SDK-side mirror of that interpretation. Builders and consent UIs should\n * work with the grouped `{ scope, actions }` view (see\n * {@link grantPermissions}) and never construct or parse the strings by hand.\n *\n * Matching rules, pinned by the Personal Server policy\n * (personal-server-ts `packages/core/src/policy/data-write.ts` and\n * `data-read.ts`):\n * - the operation is compared exactly, case-sensitively;\n * - wildcards apply to the scope part only, via {@link scopeMatchesPattern};\n * - an entry whose operation is not recognised never authorizes anything.\n * The parser fails closed on it (throws) rather than treating it as read;\n * the matcher ({@link hasAction}) skips it, which is how the Personal\n * Server treats an entry it does not understand.\n */\n\n/** Operations the grammar defines today, in canonical (output) order. */\nexport const SCOPE_ACTIONS = [\"read\", \"write\"] as const;\n\n/** An operation a grant entry can authorize over a scope. */\nexport type ScopeAction = (typeof SCOPE_ACTIONS)[number];\n\n/** One grant entry, split into its operation and scope pattern. */\nexport interface ParsedScopeEntry {\n scope: string;\n action: ScopeAction;\n}\n\n/**\n * The grouped view of a grant's scope entries: one row per scope pattern\n * with every operation the grant authorizes over it.\n */\nexport interface GrantPermission {\n scope: string;\n actions: ScopeAction[];\n}\n\n/**\n * Thrown when a scope entry does not fit the grammar - an unknown or\n * malformed operation prefix, or an empty scope part.\n */\nexport class InvalidScopeEntryError extends Error {\n /** The offending entry, verbatim (unknown because it may not be a string). */\n readonly entry: unknown;\n\n constructor(entry: unknown, reason: string) {\n super(`Invalid scope entry ${describeValue(entry)}: ${reason}`);\n this.name = \"InvalidScopeEntryError\";\n this.entry = entry;\n }\n}\n\nconst OPERATION_SEPARATOR = \":\";\n\n// Render an untrusted value for an error message without ever throwing:\n// String() and JSON.stringify() both defer to the value's own toString /\n// toJSON, which a hostile JSON body can make throw.\nfunction describeValue(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (value === null) return \"null\";\n return `[${typeof value}]`;\n}\n\n// The only operation that is ever written out. Read has no prefix, and\n// `read:` is NOT an alias for it: the Personal Server's read policy matches\n// entries verbatim, so a `read:x` entry would authorize nothing there, and\n// the parser must reject it for the same reason.\nconst OPERATION_BY_PREFIX: Readonly<Record<string, ScopeAction>> = {\n write: \"write\",\n};\n\nfunction assertScopePart(entry: string, scope: string): void {\n if (scope.length === 0) {\n throw new InvalidScopeEntryError(entry, \"scope part is empty\");\n }\n if (scope.includes(OPERATION_SEPARATOR)) {\n throw new InvalidScopeEntryError(\n entry,\n `scope part must not contain \"${OPERATION_SEPARATOR}\"`,\n );\n }\n}\n\n/**\n * Split one grant scope entry into its operation and scope pattern.\n *\n * - `notes.entries` parses as `{ scope: \"notes.entries\", action: \"read\" }`\n * - `write:notes.*` parses as `{ scope: \"notes.*\", action: \"write\" }`\n *\n * Fails closed: a non-string entry, or an entry whose operation prefix is\n * not recognised (including\n * `read:`, any uppercase or non-ASCII prefix, or a wildcard in the operation\n * position) throws {@link InvalidScopeEntryError} and is never treated as a\n * read entry. An empty scope part (`write:`) throws as well.\n *\n * @param entry - A single element of a grant's `scopes` array.\n * @returns The operation and the scope pattern it applies to.\n * @throws InvalidScopeEntryError when the entry does not fit the grammar.\n */\nexport function parseScopeEntry(entry: string): ParsedScopeEntry {\n // Grant bodies arrive from the network; a non-string element is a grammar\n // violation like any other, not a TypeError from indexOf.\n const raw: unknown = entry;\n if (typeof raw !== \"string\") {\n throw new InvalidScopeEntryError(raw, \"entry must be a string\");\n }\n const separatorIndex = entry.indexOf(OPERATION_SEPARATOR);\n if (separatorIndex === -1) {\n assertScopePart(entry, entry);\n return { scope: entry, action: \"read\" };\n }\n\n const prefix = entry.slice(0, separatorIndex);\n const scope = entry.slice(separatorIndex + 1);\n const action = Object.hasOwn(OPERATION_BY_PREFIX, prefix)\n ? OPERATION_BY_PREFIX[prefix]\n : undefined;\n if (action === undefined) {\n throw new InvalidScopeEntryError(\n entry,\n `unknown operation \"${prefix}\" (known: ${Object.keys(OPERATION_BY_PREFIX).join(\", \")}; read has no prefix)`,\n );\n }\n assertScopePart(entry, scope);\n return { scope, action };\n}\n\n/**\n * Inverse of {@link parseScopeEntry}: render one operation over one scope\n * pattern as a grant scope entry. Read has no prefix.\n *\n * @param parsed - The operation and scope pattern to encode.\n * @returns The wire-form entry, e.g. `write:notes.entries` or `notes.entries`.\n * @throws InvalidScopeEntryError when the action is unknown or the scope part\n * is empty or contains `:`.\n */\nexport function formatScopeEntry(parsed: ParsedScopeEntry): string {\n const { scope, action } = parsed;\n assertScopePart(scope, scope);\n if (action === \"read\") return scope;\n // Looked up rather than hard-coded so an action can never be emitted\n // without a prefix the parser accepts (and JS callers passing an unknown\n // action fail closed instead of producing a read entry).\n const prefix = Object.entries(OPERATION_BY_PREFIX).find(\n ([, candidate]) => candidate === action,\n )?.[0];\n if (prefix === undefined) {\n throw new InvalidScopeEntryError(\n scope,\n `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(\", \")})`,\n );\n }\n return `${prefix}${OPERATION_SEPARATOR}${scope}`;\n}\n\nfunction compareScopes(a: string, b: string): number {\n // Plain code-unit order: locale-independent, so the grouping is identical\n // on every runtime.\n if (a < b) return -1;\n if (a > b) return 1;\n return 0;\n}\n\nfunction sortActions(actions: Iterable<ScopeAction>): ScopeAction[] {\n const present = new Set(actions);\n return SCOPE_ACTIONS.filter((action) => present.has(action));\n}\n\n/**\n * Group a grant's scope entries into one `{ scope, actions }` row per scope\n * pattern - the view builders and consent UIs should render instead of the\n * raw strings.\n *\n * The result is canonical: rows are ordered by scope (code-unit order),\n * actions within a row follow {@link SCOPE_ACTIONS} order, and neither rows\n * nor actions repeat, whatever order or duplication the input had.\n *\n * Fails closed: if any entry does not fit the grammar this throws\n * {@link InvalidScopeEntryError} rather than silently dropping it, so a grant\n * carrying an operation this SDK does not know is never shown as narrower\n * than it is.\n *\n * @param scopes - A grant's `scopes` array, verbatim.\n * @returns The grouped, canonically ordered permissions.\n * @throws InvalidScopeEntryError when any entry does not fit the grammar.\n */\nexport function grantPermissions(scopes: readonly string[]): GrantPermission[] {\n const byScope = new Map<string, Set<ScopeAction>>();\n for (const entry of scopes) {\n const { scope, action } = parseScopeEntry(entry);\n let actions = byScope.get(scope);\n if (actions === undefined) {\n actions = new Set<ScopeAction>();\n byScope.set(scope, actions);\n }\n actions.add(action);\n }\n return [...byScope.keys()].sort(compareScopes).map((scope) => ({\n scope,\n actions: sortActions(byScope.get(scope) ?? []),\n }));\n}\n\n/**\n * Inverse of {@link grantPermissions}: flatten grouped permissions back into\n * the `string[]` form a grant is signed with.\n *\n * Output is canonical (scopes in code-unit order, read before write, no\n * duplicates), so `permissionsToScopes(grantPermissions(scopes))` is the\n * canonical form of `scopes`, and `grantPermissions(permissionsToScopes(p))`\n * is the canonical form of `p`. Rows with no actions contribute nothing; a\n * row with an action the grammar does not define throws rather than being\n * dropped.\n *\n * @param permissions - Grouped permissions, in any order, possibly repeating\n * a scope.\n * @returns The scope entries, one per (scope, action) pair.\n * @throws InvalidScopeEntryError when a scope or action does not fit the\n * grammar.\n */\nexport function permissionsToScopes(\n permissions: readonly GrantPermission[],\n): string[] {\n const byScope = new Map<string, Set<ScopeAction>>();\n for (const { scope, actions } of permissions) {\n let merged = byScope.get(scope);\n if (merged === undefined) {\n merged = new Set<ScopeAction>();\n byScope.set(scope, merged);\n }\n for (const action of actions) {\n if (!(SCOPE_ACTIONS as readonly string[]).includes(action)) {\n throw new InvalidScopeEntryError(\n scope,\n `unknown action ${describeValue(action)} (known: ${SCOPE_ACTIONS.join(\", \")})`,\n );\n }\n merged.add(action);\n }\n }\n const entries: string[] = [];\n for (const scope of [...byScope.keys()].sort(compareScopes)) {\n for (const action of sortActions(byScope.get(scope) ?? [])) {\n entries.push(formatScopeEntry({ scope, action }));\n }\n }\n return entries;\n}\n\n/**\n * Does this grant authorize `action` over `scope`?\n *\n * The scope part is matched with the SDK's scope wildcard matcher\n * ({@link scopeMatchesPattern}: `*`, `{prefix}.*`, or exact), the action\n * exactly. Entries that do not fit the grammar are skipped - they authorize\n * nothing, which is exactly how the Personal Server treats them - so a grant\n * that carries an operation this SDK does not know still answers correctly\n * for the operations it does.\n *\n * @param scopes - A grant's `scopes` array, verbatim.\n * @param scope - The concrete scope being requested. Never prefixed: a value\n * containing `:` is not a scope id and yields `false`.\n * @param action - The operation being requested.\n * @returns `true` if some entry grants `action` over a pattern covering\n * `scope`.\n */\nexport function hasAction(\n scopes: readonly string[],\n scope: string,\n action: ScopeAction,\n): boolean {\n // A requested scope is a concrete scope id and never carries a prefix; the\n // Personal Server rejects anything else with ScopeSchema before it ever\n // reaches its matcher, so answer the same way here instead of letting\n // `write:x` fall through to a `*` entry.\n if (scope.includes(OPERATION_SEPARATOR)) return false;\n for (const entry of scopes) {\n let parsed: ParsedScopeEntry;\n try {\n parsed = parseScopeEntry(entry);\n } catch (error) {\n if (error instanceof InvalidScopeEntryError) continue;\n throw error;\n }\n if (parsed.action === action && scopeMatchesPattern(scope, parsed.scope)) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * {@link grantPermissions} for a grant record read back from the gateway:\n * returns `undefined` instead of throwing when the scope list carries an\n * entry this SDK version cannot interpret, so a grant with a newer operation\n * still loads (with `scopes` intact) rather than failing the whole read.\n *\n * @param scopes - A grant's `scopes` array, verbatim.\n * @returns The grouped permissions, or `undefined` if any entry is\n * uninterpretable.\n */\nexport function tryGrantPermissions(\n scopes: readonly string[],\n): GrantPermission[] | undefined {\n try {\n return grantPermissions(scopes);\n } catch (error) {\n if (error instanceof InvalidScopeEntryError) return undefined;\n throw error;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var write_signer_exports = {};
|
|
20
|
+
__export(write_signer_exports, {
|
|
21
|
+
resolveWriteSigner: () => resolveWriteSigner
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(write_signer_exports);
|
|
24
|
+
var import_errors = require("../errors");
|
|
25
|
+
function isRecord(value) {
|
|
26
|
+
return value !== null && typeof value === "object";
|
|
27
|
+
}
|
|
28
|
+
function isViemWriteAccount(source) {
|
|
29
|
+
return isRecord(source) && source.type === "local" && typeof source.address === "string" && typeof source.signMessage === "function";
|
|
30
|
+
}
|
|
31
|
+
function isViemWriteWalletClient(source) {
|
|
32
|
+
return isRecord(source) && typeof source.signMessage === "function" && source.type !== "local" && (source.type === "walletClient" || "transport" in source);
|
|
33
|
+
}
|
|
34
|
+
function accountAddress(account) {
|
|
35
|
+
return typeof account === "string" ? account : account.address;
|
|
36
|
+
}
|
|
37
|
+
function resolveWriteSigner(source, options = {}) {
|
|
38
|
+
if (isViemWriteWalletClient(source)) {
|
|
39
|
+
const account = options.account ?? source.account;
|
|
40
|
+
if (account === void 0) {
|
|
41
|
+
throw new import_errors.WriteRequestError(
|
|
42
|
+
"Viem wallet client requires an account option or account property"
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
address: accountAddress(account),
|
|
47
|
+
signMessage: (message) => source.signMessage({ account, message })
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
if (isViemWriteAccount(source)) {
|
|
51
|
+
return {
|
|
52
|
+
address: source.address,
|
|
53
|
+
signMessage: (message) => source.signMessage({ message })
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
if (!isRecord(source) || typeof source.signMessage !== "function") {
|
|
57
|
+
throw new import_errors.WriteRequestError(
|
|
58
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return source;
|
|
62
|
+
}
|
|
63
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
64
|
+
0 && (module.exports = {
|
|
65
|
+
resolveWriteSigner
|
|
66
|
+
});
|
|
67
|
+
//# sourceMappingURL=write-signer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/write-signer.ts"],"sourcesContent":["/**\n * Builder key abstraction shared by the Write API and lineage reads.\n *\n * @remarks\n * Everything the Personal Server asks a builder to sign is an EIP-191\n * `personal_sign` over a Web3Signed payload, so one `signMessage` callback is\n * the whole contract. {@link resolveWriteSigner} accepts the shapes a builder\n * already has: a viem `LocalAccount` (backend, `privateKeyToAccount`), a viem\n * `WalletClient` (browser wallet), or a bare `{ signMessage }` object.\n *\n * @category Protocol\n */\n\nimport type { Account, Address, Hex } from \"viem\";\nimport type { Web3SignedSignFn } from \"../auth/web3-signed-builder\";\nimport { WriteRequestError } from \"../errors\";\n\n/** The signer the Write API drives: an EIP-191 signature over a string. */\nexport interface WriteSigner {\n /** The builder address, when known. Used for messages only. */\n address?: Address;\n /** EIP-191 (`personal_sign`) over the Web3Signed payload string. */\n signMessage: Web3SignedSignFn;\n}\n\n/** The subset of a viem `LocalAccount` the Write API uses. */\nexport interface ViemWriteAccount {\n address: Address;\n type: \"local\";\n signMessage(args: { message: string }): Promise<Hex>;\n}\n\n/** The subset of a viem `WalletClient` the Write API uses. */\nexport interface ViemWriteWalletClient {\n type?: string;\n transport?: unknown;\n account?: Account | undefined;\n signMessage(args: {\n account: Account | Address;\n message: string;\n }): Promise<Hex>;\n}\n\n/** Any signer {@link resolveWriteSigner} understands. */\nexport type WriteSignerSource =\n | WriteSigner\n | ViemWriteAccount\n | ViemWriteWalletClient;\n\nexport interface ResolveWriteSignerOptions {\n /**\n * Account to sign with when the viem wallet client has no hoisted account\n * (browser wallets). Ignored for other signer shapes.\n */\n account?: Account | Address;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\";\n}\n\nfunction isViemWriteAccount(source: unknown): source is ViemWriteAccount {\n return (\n isRecord(source) &&\n source.type === \"local\" &&\n typeof source.address === \"string\" &&\n typeof source.signMessage === \"function\"\n );\n}\n\n/**\n * A viem client: `createWalletClient` stamps `type: \"walletClient\"`, and every\n * viem client carries a `transport`. Either marker is enough; a bare\n * `{ signMessage }` signer has neither, and a local account has\n * `type: \"local\"`.\n */\nfunction isViemWriteWalletClient(\n source: unknown,\n): source is ViemWriteWalletClient {\n return (\n isRecord(source) &&\n typeof source.signMessage === \"function\" &&\n source.type !== \"local\" &&\n (source.type === \"walletClient\" || \"transport\" in source)\n );\n}\n\nfunction accountAddress(account: Account | Address): Address {\n return typeof account === \"string\" ? account : account.address;\n}\n\n/**\n * Normalise a builder key into a {@link WriteSigner}.\n *\n * @param source - A viem `LocalAccount`, a viem `WalletClient`, or a\n * `{ signMessage }` object (returned as-is).\n * @param options - `account` for a wallet client without a hoisted account.\n * @returns A signer whose `signMessage` produces EIP-191 signatures.\n * @throws {WriteRequestError} When a wallet client has no account to sign\n * with, or the source exposes no `signMessage` function.\n */\nexport function resolveWriteSigner(\n source: WriteSignerSource,\n options: ResolveWriteSignerOptions = {},\n): WriteSigner {\n if (isViemWriteWalletClient(source)) {\n const account = options.account ?? source.account;\n if (account === undefined) {\n throw new WriteRequestError(\n \"Viem wallet client requires an account option or account property\",\n );\n }\n return {\n address: accountAddress(account),\n signMessage: (message) => source.signMessage({ account, message }),\n };\n }\n if (isViemWriteAccount(source)) {\n return {\n address: source.address,\n signMessage: (message) => source.signMessage({ message }),\n };\n }\n if (!isRecord(source) || typeof source.signMessage !== \"function\") {\n throw new WriteRequestError(\n \"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object\",\n );\n }\n return source as WriteSigner;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAeA,oBAAkC;AA0ClC,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU;AAC5C;AAEA,SAAS,mBAAmB,QAA6C;AACvE,SACE,SAAS,MAAM,KACf,OAAO,SAAS,WAChB,OAAO,OAAO,YAAY,YAC1B,OAAO,OAAO,gBAAgB;AAElC;AAQA,SAAS,wBACP,QACiC;AACjC,SACE,SAAS,MAAM,KACf,OAAO,OAAO,gBAAgB,cAC9B,OAAO,SAAS,YACf,OAAO,SAAS,kBAAkB,eAAe;AAEtD;AAEA,SAAS,eAAe,SAAqC;AAC3D,SAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;AACzD;AAYO,SAAS,mBACd,QACA,UAAqC,CAAC,GACzB;AACb,MAAI,wBAAwB,MAAM,GAAG;AACnC,UAAM,UAAU,QAAQ,WAAW,OAAO;AAC1C,QAAI,YAAY,QAAW;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,eAAe,OAAO;AAAA,MAC/B,aAAa,CAAC,YAAY,OAAO,YAAY,EAAE,SAAS,QAAQ,CAAC;AAAA,IACnE;AAAA,EACF;AACA,MAAI,mBAAmB,MAAM,GAAG;AAC9B,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,aAAa,CAAC,YAAY,OAAO,YAAY,EAAE,QAAQ,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,MAAI,CAAC,SAAS,MAAM,KAAK,OAAO,OAAO,gBAAgB,YAAY;AACjE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder key abstraction shared by the Write API and lineage reads.
|
|
3
|
+
*
|
|
4
|
+
* @remarks
|
|
5
|
+
* Everything the Personal Server asks a builder to sign is an EIP-191
|
|
6
|
+
* `personal_sign` over a Web3Signed payload, so one `signMessage` callback is
|
|
7
|
+
* the whole contract. {@link resolveWriteSigner} accepts the shapes a builder
|
|
8
|
+
* already has: a viem `LocalAccount` (backend, `privateKeyToAccount`), a viem
|
|
9
|
+
* `WalletClient` (browser wallet), or a bare `{ signMessage }` object.
|
|
10
|
+
*
|
|
11
|
+
* @category Protocol
|
|
12
|
+
*/
|
|
13
|
+
import type { Account, Address, Hex } from "viem";
|
|
14
|
+
import type { Web3SignedSignFn } from "../auth/web3-signed-builder.js";
|
|
15
|
+
/** The signer the Write API drives: an EIP-191 signature over a string. */
|
|
16
|
+
export interface WriteSigner {
|
|
17
|
+
/** The builder address, when known. Used for messages only. */
|
|
18
|
+
address?: Address;
|
|
19
|
+
/** EIP-191 (`personal_sign`) over the Web3Signed payload string. */
|
|
20
|
+
signMessage: Web3SignedSignFn;
|
|
21
|
+
}
|
|
22
|
+
/** The subset of a viem `LocalAccount` the Write API uses. */
|
|
23
|
+
export interface ViemWriteAccount {
|
|
24
|
+
address: Address;
|
|
25
|
+
type: "local";
|
|
26
|
+
signMessage(args: {
|
|
27
|
+
message: string;
|
|
28
|
+
}): Promise<Hex>;
|
|
29
|
+
}
|
|
30
|
+
/** The subset of a viem `WalletClient` the Write API uses. */
|
|
31
|
+
export interface ViemWriteWalletClient {
|
|
32
|
+
type?: string;
|
|
33
|
+
transport?: unknown;
|
|
34
|
+
account?: Account | undefined;
|
|
35
|
+
signMessage(args: {
|
|
36
|
+
account: Account | Address;
|
|
37
|
+
message: string;
|
|
38
|
+
}): Promise<Hex>;
|
|
39
|
+
}
|
|
40
|
+
/** Any signer {@link resolveWriteSigner} understands. */
|
|
41
|
+
export type WriteSignerSource = WriteSigner | ViemWriteAccount | ViemWriteWalletClient;
|
|
42
|
+
export interface ResolveWriteSignerOptions {
|
|
43
|
+
/**
|
|
44
|
+
* Account to sign with when the viem wallet client has no hoisted account
|
|
45
|
+
* (browser wallets). Ignored for other signer shapes.
|
|
46
|
+
*/
|
|
47
|
+
account?: Account | Address;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Normalise a builder key into a {@link WriteSigner}.
|
|
51
|
+
*
|
|
52
|
+
* @param source - A viem `LocalAccount`, a viem `WalletClient`, or a
|
|
53
|
+
* `{ signMessage }` object (returned as-is).
|
|
54
|
+
* @param options - `account` for a wallet client without a hoisted account.
|
|
55
|
+
* @returns A signer whose `signMessage` produces EIP-191 signatures.
|
|
56
|
+
* @throws {WriteRequestError} When a wallet client has no account to sign
|
|
57
|
+
* with, or the source exposes no `signMessage` function.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveWriteSigner(source: WriteSignerSource, options?: ResolveWriteSignerOptions): WriteSigner;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { WriteRequestError } from "../errors.js";
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return value !== null && typeof value === "object";
|
|
4
|
+
}
|
|
5
|
+
function isViemWriteAccount(source) {
|
|
6
|
+
return isRecord(source) && source.type === "local" && typeof source.address === "string" && typeof source.signMessage === "function";
|
|
7
|
+
}
|
|
8
|
+
function isViemWriteWalletClient(source) {
|
|
9
|
+
return isRecord(source) && typeof source.signMessage === "function" && source.type !== "local" && (source.type === "walletClient" || "transport" in source);
|
|
10
|
+
}
|
|
11
|
+
function accountAddress(account) {
|
|
12
|
+
return typeof account === "string" ? account : account.address;
|
|
13
|
+
}
|
|
14
|
+
function resolveWriteSigner(source, options = {}) {
|
|
15
|
+
if (isViemWriteWalletClient(source)) {
|
|
16
|
+
const account = options.account ?? source.account;
|
|
17
|
+
if (account === void 0) {
|
|
18
|
+
throw new WriteRequestError(
|
|
19
|
+
"Viem wallet client requires an account option or account property"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
address: accountAddress(account),
|
|
24
|
+
signMessage: (message) => source.signMessage({ account, message })
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
if (isViemWriteAccount(source)) {
|
|
28
|
+
return {
|
|
29
|
+
address: source.address,
|
|
30
|
+
signMessage: (message) => source.signMessage({ message })
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
if (!isRecord(source) || typeof source.signMessage !== "function") {
|
|
34
|
+
throw new WriteRequestError(
|
|
35
|
+
"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
return source;
|
|
39
|
+
}
|
|
40
|
+
export {
|
|
41
|
+
resolveWriteSigner
|
|
42
|
+
};
|
|
43
|
+
//# sourceMappingURL=write-signer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol/write-signer.ts"],"sourcesContent":["/**\n * Builder key abstraction shared by the Write API and lineage reads.\n *\n * @remarks\n * Everything the Personal Server asks a builder to sign is an EIP-191\n * `personal_sign` over a Web3Signed payload, so one `signMessage` callback is\n * the whole contract. {@link resolveWriteSigner} accepts the shapes a builder\n * already has: a viem `LocalAccount` (backend, `privateKeyToAccount`), a viem\n * `WalletClient` (browser wallet), or a bare `{ signMessage }` object.\n *\n * @category Protocol\n */\n\nimport type { Account, Address, Hex } from \"viem\";\nimport type { Web3SignedSignFn } from \"../auth/web3-signed-builder\";\nimport { WriteRequestError } from \"../errors\";\n\n/** The signer the Write API drives: an EIP-191 signature over a string. */\nexport interface WriteSigner {\n /** The builder address, when known. Used for messages only. */\n address?: Address;\n /** EIP-191 (`personal_sign`) over the Web3Signed payload string. */\n signMessage: Web3SignedSignFn;\n}\n\n/** The subset of a viem `LocalAccount` the Write API uses. */\nexport interface ViemWriteAccount {\n address: Address;\n type: \"local\";\n signMessage(args: { message: string }): Promise<Hex>;\n}\n\n/** The subset of a viem `WalletClient` the Write API uses. */\nexport interface ViemWriteWalletClient {\n type?: string;\n transport?: unknown;\n account?: Account | undefined;\n signMessage(args: {\n account: Account | Address;\n message: string;\n }): Promise<Hex>;\n}\n\n/** Any signer {@link resolveWriteSigner} understands. */\nexport type WriteSignerSource =\n | WriteSigner\n | ViemWriteAccount\n | ViemWriteWalletClient;\n\nexport interface ResolveWriteSignerOptions {\n /**\n * Account to sign with when the viem wallet client has no hoisted account\n * (browser wallets). Ignored for other signer shapes.\n */\n account?: Account | Address;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\";\n}\n\nfunction isViemWriteAccount(source: unknown): source is ViemWriteAccount {\n return (\n isRecord(source) &&\n source.type === \"local\" &&\n typeof source.address === \"string\" &&\n typeof source.signMessage === \"function\"\n );\n}\n\n/**\n * A viem client: `createWalletClient` stamps `type: \"walletClient\"`, and every\n * viem client carries a `transport`. Either marker is enough; a bare\n * `{ signMessage }` signer has neither, and a local account has\n * `type: \"local\"`.\n */\nfunction isViemWriteWalletClient(\n source: unknown,\n): source is ViemWriteWalletClient {\n return (\n isRecord(source) &&\n typeof source.signMessage === \"function\" &&\n source.type !== \"local\" &&\n (source.type === \"walletClient\" || \"transport\" in source)\n );\n}\n\nfunction accountAddress(account: Account | Address): Address {\n return typeof account === \"string\" ? account : account.address;\n}\n\n/**\n * Normalise a builder key into a {@link WriteSigner}.\n *\n * @param source - A viem `LocalAccount`, a viem `WalletClient`, or a\n * `{ signMessage }` object (returned as-is).\n * @param options - `account` for a wallet client without a hoisted account.\n * @returns A signer whose `signMessage` produces EIP-191 signatures.\n * @throws {WriteRequestError} When a wallet client has no account to sign\n * with, or the source exposes no `signMessage` function.\n */\nexport function resolveWriteSigner(\n source: WriteSignerSource,\n options: ResolveWriteSignerOptions = {},\n): WriteSigner {\n if (isViemWriteWalletClient(source)) {\n const account = options.account ?? source.account;\n if (account === undefined) {\n throw new WriteRequestError(\n \"Viem wallet client requires an account option or account property\",\n );\n }\n return {\n address: accountAddress(account),\n signMessage: (message) => source.signMessage({ account, message }),\n };\n }\n if (isViemWriteAccount(source)) {\n return {\n address: source.address,\n signMessage: (message) => source.signMessage({ message }),\n };\n }\n if (!isRecord(source) || typeof source.signMessage !== \"function\") {\n throw new WriteRequestError(\n \"signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object\",\n );\n }\n return source as WriteSigner;\n}\n"],"mappings":"AAeA,SAAS,yBAAyB;AA0ClC,SAAS,SAAS,OAAkD;AAClE,SAAO,UAAU,QAAQ,OAAO,UAAU;AAC5C;AAEA,SAAS,mBAAmB,QAA6C;AACvE,SACE,SAAS,MAAM,KACf,OAAO,SAAS,WAChB,OAAO,OAAO,YAAY,YAC1B,OAAO,OAAO,gBAAgB;AAElC;AAQA,SAAS,wBACP,QACiC;AACjC,SACE,SAAS,MAAM,KACf,OAAO,OAAO,gBAAgB,cAC9B,OAAO,SAAS,YACf,OAAO,SAAS,kBAAkB,eAAe;AAEtD;AAEA,SAAS,eAAe,SAAqC;AAC3D,SAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;AACzD;AAYO,SAAS,mBACd,QACA,UAAqC,CAAC,GACzB;AACb,MAAI,wBAAwB,MAAM,GAAG;AACnC,UAAM,UAAU,QAAQ,WAAW,OAAO;AAC1C,QAAI,YAAY,QAAW;AACzB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,eAAe,OAAO;AAAA,MAC/B,aAAa,CAAC,YAAY,OAAO,YAAY,EAAE,SAAS,QAAQ,CAAC;AAAA,IACnE;AAAA,EACF;AACA,MAAI,mBAAmB,MAAM,GAAG;AAC9B,WAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,aAAa,CAAC,YAAY,OAAO,YAAY,EAAE,QAAQ,CAAC;AAAA,IAC1D;AAAA,EACF;AACA,MAAI,CAAC,SAAS,MAAM,KAAK,OAAO,OAAO,gBAAgB,YAAY;AACjE,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory Personal Server + gateway that enforce the Write API contract the
|
|
3
|
+
* way `personal-server-ts` does (routes/write-session.ts, api-auth.ts,
|
|
4
|
+
* write/attribution.ts, contracts/binary.ts), so the SDK client is tested
|
|
5
|
+
* against the real rules rather than a permissive stub:
|
|
6
|
+
*
|
|
7
|
+
* - handshake: Web3Signed proof, grantId claim required, grant must carry
|
|
8
|
+
* `write:` entries, signer must be the grantee, proof single-use
|
|
9
|
+
* - write: bearer must resolve to a live session, scope must be covered by
|
|
10
|
+
* the session's write patterns, X-Vana-Write-Signature must recover to
|
|
11
|
+
* the session builder over the STORED representation (body for JSON,
|
|
12
|
+
* the `$binary` record for anything else), carry the session grantId as
|
|
13
|
+
* a signed claim, JSON bodies must be compact, reserved keys rejected,
|
|
14
|
+
* proof single-use; `lineage` is the body's top-level field (JSON) or
|
|
15
|
+
* the metadata object's field (binary), validated per
|
|
16
|
+
* docs/derivative-data-api.md and mirrored to `$lineage`
|
|
17
|
+
* - lineage reads on both the Personal Server and the gateway: Web3Signed
|
|
18
|
+
* over the bare path (`/lineage[/:version]`, the version is a path
|
|
19
|
+
* segment, any query is 400), grant view from the signed `grantId` claim
|
|
20
|
+
* only, 401 for a missing / invalid gateway signature, a uniform 404 for
|
|
21
|
+
* an unknown id and for a signer the gateway will not serve; answering
|
|
22
|
+
* the `{ data, proof }` envelope with redaction for nodes the caller's
|
|
23
|
+
* grant does not cover
|
|
24
|
+
*
|
|
25
|
+
* The binary representation is a verbatim port of the Personal Server's
|
|
26
|
+
* `buildBinaryEnvelopeData` / `parseMetadataHeader` (Web Crypto + btoa), so
|
|
27
|
+
* it is an independent oracle for the SDK's `binaryWriteSignedBytes`.
|
|
28
|
+
*/
|
|
29
|
+
import { type Address, type Hex } from "viem";
|
|
30
|
+
export interface MockGrant {
|
|
31
|
+
id: string;
|
|
32
|
+
grantorAddress: Address;
|
|
33
|
+
granteeId: Address;
|
|
34
|
+
scopes: string[];
|
|
35
|
+
revokedAt?: string | null;
|
|
36
|
+
}
|
|
37
|
+
export interface MockStoredRecord {
|
|
38
|
+
scope: string;
|
|
39
|
+
collectedAt: string;
|
|
40
|
+
data: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
export interface MockLineageSource {
|
|
43
|
+
dataPointId: Hex;
|
|
44
|
+
scope: string;
|
|
45
|
+
version: string;
|
|
46
|
+
deletedAt: string | null;
|
|
47
|
+
}
|
|
48
|
+
export interface MockPersonalServerOptions {
|
|
49
|
+
origin: string;
|
|
50
|
+
owner: Address;
|
|
51
|
+
grants: MockGrant[];
|
|
52
|
+
/** Data points a lineage source may reference (id -> node). */
|
|
53
|
+
knownDataPoints?: MockLineageSource[];
|
|
54
|
+
/** Fixed ingest status. */
|
|
55
|
+
status?: "stored" | "syncing";
|
|
56
|
+
sessionTtlSeconds?: number;
|
|
57
|
+
now?: () => number;
|
|
58
|
+
}
|
|
59
|
+
export interface MockRequestLog {
|
|
60
|
+
method: string;
|
|
61
|
+
path: string;
|
|
62
|
+
headers: Record<string, string>;
|
|
63
|
+
body: Uint8Array;
|
|
64
|
+
}
|
|
65
|
+
export interface MockPersonalServer {
|
|
66
|
+
fetch: typeof fetch;
|
|
67
|
+
origin: string;
|
|
68
|
+
records: MockStoredRecord[];
|
|
69
|
+
requests: MockRequestLog[];
|
|
70
|
+
/** Handshake and write proofs consumed so far (sha-256 hex of the header). */
|
|
71
|
+
proofsSeen: Set<string>;
|
|
72
|
+
/** Make the next `n` fetches throw (transport failure) before answering. */
|
|
73
|
+
failNext(n: number, error?: Error): void;
|
|
74
|
+
/** Force the next response (any route). */
|
|
75
|
+
respondNextWith(status: number, body: unknown): void;
|
|
76
|
+
/** Sessions minted (token -> record). */
|
|
77
|
+
sessions: Map<string, MockSession>;
|
|
78
|
+
}
|
|
79
|
+
export interface MockSession {
|
|
80
|
+
token: string;
|
|
81
|
+
builderAddress: Address;
|
|
82
|
+
grantId: string;
|
|
83
|
+
writeScopes: string[];
|
|
84
|
+
expiresAtMs: number;
|
|
85
|
+
}
|
|
86
|
+
/** The Personal Server's `binaryWriteSignedBytes`, ported for the oracle. */
|
|
87
|
+
export declare function personalServerBinaryWriteSignedBytes(input: {
|
|
88
|
+
bytes: Uint8Array;
|
|
89
|
+
contentType: string;
|
|
90
|
+
filename?: string;
|
|
91
|
+
metadataHeader?: string;
|
|
92
|
+
}): Promise<Uint8Array>;
|
|
93
|
+
/** A Personal Server that enforces the Write API contract, as a `fetch`. */
|
|
94
|
+
export declare function createMockPersonalServer(options: MockPersonalServerOptions): MockPersonalServer;
|
|
95
|
+
export interface MockGatewayOptions {
|
|
96
|
+
origin: string;
|
|
97
|
+
/** Lineage views by data point id (lowercase). */
|
|
98
|
+
graphs: Record<string, MockGatewayView>;
|
|
99
|
+
/** Builder address -> grant ids it holds (lowercase), for the 404 rule. */
|
|
100
|
+
grants?: Record<string, string[]>;
|
|
101
|
+
/** Wrap answers in the gateway `{ data, proof }` envelope (default true). */
|
|
102
|
+
envelope?: boolean;
|
|
103
|
+
now?: () => number;
|
|
104
|
+
}
|
|
105
|
+
export interface MockGatewayView {
|
|
106
|
+
dataPointId: Hex;
|
|
107
|
+
ownerAddress?: Address;
|
|
108
|
+
scope: string;
|
|
109
|
+
version: string;
|
|
110
|
+
deletedAt: string | null;
|
|
111
|
+
sources: unknown[];
|
|
112
|
+
derivatives: unknown[];
|
|
113
|
+
derivativesTruncated?: boolean;
|
|
114
|
+
}
|
|
115
|
+
export interface MockGateway {
|
|
116
|
+
fetch: typeof fetch;
|
|
117
|
+
requests: MockRequestLog[];
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A gateway answering `GET /v1/data/:id/lineage[/:version]`: the version is
|
|
121
|
+
* a path segment and any query string is 400; the request must carry a
|
|
122
|
+
* Web3Signed header whose `uri` is that bare path (401
|
|
123
|
+
* LINEAGE_SIGNATURE_REQUIRED / LINEAGE_SIGNATURE_INVALID otherwise); the
|
|
124
|
+
* grant view is the signed `grantId` claim; an unknown id and a signer that
|
|
125
|
+
* holds no such grant both answer a uniform 404.
|
|
126
|
+
*/
|
|
127
|
+
export declare function createMockGateway(options: MockGatewayOptions): MockGateway;
|