@newton-xyz/policy-pack-shared 0.1.1 → 0.2.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/dist/index.cjs CHANGED
@@ -21,10 +21,35 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  UnsupportedChainError: () => UnsupportedChainError,
24
+ decodePolicyParams: () => decodePolicyParams,
25
+ encodePolicyParams: () => encodePolicyParams,
24
26
  getDeployment: () => getDeployment
25
27
  });
26
28
  module.exports = __toCommonJS(index_exports);
27
29
 
30
+ // src/encoding.ts
31
+ var import_viem = require("viem");
32
+ function sortKeysDeep(value) {
33
+ if (Array.isArray(value)) return value.map(sortKeysDeep);
34
+ if (value && typeof value === "object") {
35
+ const obj = value;
36
+ const sorted = {};
37
+ for (const key of Object.keys(obj).sort()) {
38
+ sorted[key] = sortKeysDeep(obj[key]);
39
+ }
40
+ return sorted;
41
+ }
42
+ return value;
43
+ }
44
+ function encodePolicyParams(pack, params) {
45
+ const validated = pack.paramsSchema.parse(params);
46
+ return (0, import_viem.toHex)(JSON.stringify(sortKeysDeep(validated)));
47
+ }
48
+ function decodePolicyParams(pack, encoded) {
49
+ const json = new TextDecoder("utf-8", { fatal: true }).decode((0, import_viem.hexToBytes)(encoded));
50
+ return pack.paramsSchema.parse(JSON.parse(json));
51
+ }
52
+
28
53
  // src/pack.ts
29
54
  function getDeployment(pack, chainId) {
30
55
  const deployment = pack.deployments[chainId];
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/pack.ts"],"sourcesContent":["export type { ChainId, Deployment } from \"./deployment\";\nexport type {\n\tPolicyPack,\n\tPrepareQueryArgs,\n\tPrepareQueryResult,\n} from \"./pack\";\nexport {\n\tgetDeployment,\n\tUnsupportedChainError,\n} from \"./pack\";\n","import type { Address, Hex, PublicClient } from \"viem\";\nimport type { z } from \"zod\";\nimport type { ChainId, Deployment } from \"./deployment\";\n\n/**\n * Inputs that a pack's `prepareQuery` reads at intent-build time.\n *\n * The Shield SDK passes a viem `PublicClient` (so the pack can read on-chain\n * state) and the vault address the curator is acting on. Packs that don't\n * need on-chain state can ignore both — `prepareQuery` is optional.\n */\nexport interface PrepareQueryArgs {\n\treadonly publicClient: PublicClient;\n\treadonly vault: Address;\n}\n\n/**\n * `wasmArgs` payload (untyped at this layer; each pack narrows it via its own\n * `WasmArgsSchema`) plus an optional pre-image hash for binding the AVS-side\n * evaluation to a specific on-chain state. VaultsFYI uses this to bind the\n * evaluation to a `keccak(supplyQueue)` snapshot so the policy can reject\n * attestations whose underlying allocation has shifted between intent build\n * and on-chain submission.\n */\nexport interface PrepareQueryResult<TWasmArgs> {\n\treadonly wasmArgs: TWasmArgs;\n\treadonly freshnessHash?: Hex;\n}\n\n/**\n * Canonical typed contract every published `@newton-xyz/policy-pack-<name>`\n * package implements. `@newton-xyz/newton-shield-sdk`'s `createShield(...)`\n * accepts `PolicyPack<P, W, S>` as the curator's pack argument.\n *\n * Type parameters:\n * - `TParams` — the shape stored on-chain in `NewtonPolicyData.policyParams`\n * (e.g. risk envelope thresholds for VaultsFYI).\n * - `TWasmArgs` — the shape passed to the policy's WASM oracle at evaluation\n * time (e.g. `{ vault, network, lastKnownAllocationHash }`).\n * - `TSecrets` — required API credentials uploaded before any run/sim.\n *\n * The fields:\n * - `id` — stable identifier of the form `<pack>/<purpose>/<version>`,\n * e.g. `vaultsfyi/risk-envelope/v1`. Used for telemetry\n * and for cross-referencing the `policy_metadata.json`.\n * - `paramsSchema` — zod schema enforced at curator setup time when the\n * pack is bound to a `NewtonPolicyData`.\n * - `wasmArgsSchema` — zod schema enforced per call when the SDK builds the\n * intent and forwards `wasmArgs` to the gateway.\n * - `secretsSchema` — zod schema enforced at upload-time. Validates the\n * shape of the secrets the operator stores in the AVS.\n * - `encodeParams` / `decodeParams` — ABI round-trip for the on-chain\n * `policyParams` bytes. Must round-trip cleanly so the\n * SDK can read the on-chain value back and confirm it\n * matches the curator's intended config.\n * - `prepareQuery` — optional. When present, the SDK invokes it on every\n * call to gather chain-state freshness inputs. Packs\n * that don't need this (e.g. KYC-only packs) omit it.\n * The optional second `options` argument is a\n * pack-typed escape hatch for per-call overrides —\n * e.g. VaultsFYI's `previousAllocationHash` for\n * freshness binding. Each concrete pack narrows it\n * via its own `prepareQuery` signature; the shared\n * interface keeps it `unknown` so the SDK can\n * forward it verbatim.\n * - `deployments` — `chainId → Deployment` map sliced from the upstream\n * `deployments.json` for this pack only. Typed as\n * `Partial<Record<ChainId, Deployment>>` so callers\n * must handle `undefined` for unsupported chains\n * rather than silently reading `.policy` off nothing.\n * Use `getDeployment(pack, chainId)` from this package\n * for the safe lookup.\n * - `metadata` — static identity from the pack's `policy_metadata.json`.\n */\nexport interface PolicyPack<TParams, TWasmArgs, TSecrets> {\n\treadonly id: string;\n\treadonly paramsSchema: z.ZodType<TParams>;\n\treadonly wasmArgsSchema: z.ZodType<TWasmArgs>;\n\treadonly secretsSchema: z.ZodType<TSecrets>;\n\tencodeParams(params: TParams): Hex;\n\tdecodeParams(encoded: Hex): TParams;\n\tprepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;\n\treadonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;\n\treadonly metadata: {\n\t\treadonly name: string;\n\t\treadonly version: string;\n\t\treadonly description: string;\n\t\treadonly author?: string;\n\t\treadonly link?: string;\n\t};\n}\n\n/**\n * Safe lookup helper. Returns the `Deployment` for `chainId` if the pack is\n * deployed on that chain, or throws `UnsupportedChainError` with the list of\n * chain ids the pack is known to support. Use this at every SDK callsite that\n * reads `pack.deployments[chainId]` so unsupported-chain failures surface\n * immediately rather than as `undefined.policy` further down.\n */\nexport function getDeployment<TParams, TWasmArgs, TSecrets>(\n\tpack: PolicyPack<TParams, TWasmArgs, TSecrets>,\n\tchainId: ChainId,\n): Deployment {\n\tconst deployment = pack.deployments[chainId];\n\tif (!deployment) {\n\t\tconst supported = Object.keys(pack.deployments).sort().join(\", \") || \"(none)\";\n\t\tthrow new UnsupportedChainError(\n\t\t\t`Pack \\`${pack.id}\\` is not deployed on chain ${chainId}. Supported: ${supported}.`,\n\t\t\tpack.id,\n\t\t\tchainId,\n\t\t\tObject.keys(pack.deployments),\n\t\t);\n\t}\n\treturn deployment;\n}\n\n/**\n * Thrown by `getDeployment` when a pack is asked for a chain it isn't\n * deployed on. SDK consumers can catch this specifically to surface a\n * curator-friendly error rather than a `TypeError: Cannot read property\n * 'policy' of undefined`.\n */\nexport class UnsupportedChainError extends Error {\n\toverride readonly name = \"UnsupportedChainError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly packId: string,\n\t\treadonly chainId: ChainId,\n\t\treadonly supportedChainIds: ReadonlyArray<ChainId>,\n\t) {\n\t\tsuper(message);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmGO,SAAS,cACf,MACA,SACa;AACb,QAAM,aAAa,KAAK,YAAY,OAAO;AAC3C,MAAI,CAAC,YAAY;AAChB,UAAM,YAAY,OAAO,KAAK,KAAK,WAAW,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK;AACrE,UAAM,IAAI;AAAA,MACT,UAAU,KAAK,EAAE,+BAA+B,OAAO,gBAAgB,SAAS;AAAA,MAChF,KAAK;AAAA,MACL;AAAA,MACA,OAAO,KAAK,KAAK,WAAW;AAAA,IAC7B;AAAA,EACD;AACA,SAAO;AACR;AAQO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAEhD,YACC,SACS,QACA,SACA,mBACR;AACD,UAAM,OAAO;AAJJ;AACA;AACA;AAAA,EAGV;AAAA,EALU;AAAA,EACA;AAAA,EACA;AAAA,EALQ,OAAO;AAS1B;","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/encoding.ts","../src/pack.ts"],"sourcesContent":["export type { ChainId, Deployment } from \"./deployment\";\nexport { decodePolicyParams, encodePolicyParams } from \"./encoding\";\nexport type {\n\tPolicyPack,\n\tPrepareQueryArgs,\n\tPrepareQueryResult,\n} from \"./pack\";\nexport {\n\tgetDeployment,\n\tUnsupportedChainError,\n} from \"./pack\";\n","import { type Hex, hexToBytes, toHex } from \"viem\";\nimport type { z } from \"zod\";\n\n/**\n * The on-chain `policyParams` byte format is a Newton-protocol invariant. The\n * AVS host reads it as `String::from_utf8 → serde_json::from_str` (see\n * `newton-prover-avs/crates/core/src/common/task.rs:402-408`); the SDK must\n * therefore write **UTF-8 JSON**. Keys are sorted recursively so two\n * semantically-equal params objects always produce byte-identical output —\n * the SDK's `verifyPolicyBinding` does a byte-equality check against\n * `getPolicyConfig().policyParams`, which would otherwise depend on JS\n * `JSON.stringify` insertion order.\n */\nfunction sortKeysDeep(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(sortKeysDeep);\n\tif (value && typeof value === \"object\") {\n\t\tconst obj = value as Record<string, unknown>;\n\t\tconst sorted: Record<string, unknown> = {};\n\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\tsorted[key] = sortKeysDeep(obj[key]);\n\t\t}\n\t\treturn sorted;\n\t}\n\treturn value;\n}\n\n/**\n * Encode a pack's params for on-chain storage. Validates against the pack's\n * `paramsSchema` so a curator typo throws here rather than silently writing\n * AVS-rejecting bytes. Returns `Hex` so it drops directly into a viem\n * `setPolicy(bytes)` call.\n */\nexport function encodePolicyParams<T>(\n\tpack: { readonly paramsSchema: z.ZodType<T> },\n\tparams: T,\n): Hex {\n\tconst validated = pack.paramsSchema.parse(params);\n\treturn toHex(JSON.stringify(sortKeysDeep(validated)));\n}\n\n/**\n * Decode `policyParams` bytes read from `getPolicyConfig().policyParams` back\n * into the pack's typed params shape. Revalidates against `paramsSchema` so a\n * stale or corrupted on-chain blob throws at the SDK boundary rather than\n * yielding a partially-valid object that crashes deeper in the call.\n *\n * `fatal: true` matches AVS-side `String::from_utf8` behavior — invalid UTF-8\n * throws here rather than silently becoming U+FFFD and diverging from a path\n * the AVS would reject.\n */\nexport function decodePolicyParams<T>(\n\tpack: { readonly paramsSchema: z.ZodType<T> },\n\tencoded: Hex,\n): T {\n\tconst json = new TextDecoder(\"utf-8\", { fatal: true }).decode(hexToBytes(encoded));\n\treturn pack.paramsSchema.parse(JSON.parse(json));\n}\n","import type { Address, Hex, PublicClient } from \"viem\";\nimport type { z } from \"zod\";\nimport type { ChainId, Deployment } from \"./deployment\";\n\n/**\n * Inputs that a pack's `prepareQuery` reads at intent-build time.\n *\n * The Shield SDK passes a viem `PublicClient` (so the pack can read on-chain\n * state) and the vault address the curator is acting on. Packs that don't\n * need on-chain state can ignore both — `prepareQuery` is optional.\n */\nexport interface PrepareQueryArgs {\n\treadonly publicClient: PublicClient;\n\treadonly vault: Address;\n}\n\n/**\n * `wasmArgs` payload (untyped at this layer; each pack narrows it via its own\n * `WasmArgsSchema`) plus an optional pre-image hash for binding the AVS-side\n * evaluation to a specific on-chain state. VaultsFYI uses this to bind the\n * evaluation to a `keccak(supplyQueue)` snapshot so the policy can reject\n * attestations whose underlying allocation has shifted between intent build\n * and on-chain submission.\n */\nexport interface PrepareQueryResult<TWasmArgs> {\n\treadonly wasmArgs: TWasmArgs;\n\treadonly freshnessHash?: Hex;\n}\n\n/**\n * Canonical typed contract every published `@newton-xyz/policy-pack-<name>`\n * package implements. `@newton-xyz/newton-shield-sdk`'s `createShield(...)`\n * accepts `PolicyPack<P, W, S>` as the curator's pack argument.\n *\n * Type parameters:\n * - `TParams` — the shape stored on-chain in `NewtonPolicyData.policyParams`\n * (e.g. risk envelope thresholds for VaultsFYI).\n * - `TWasmArgs` — the shape passed to the policy's WASM oracle at evaluation\n * time (e.g. `{ vault, network, lastKnownAllocationHash }`).\n * - `TSecrets` — required API credentials uploaded before any run/sim.\n *\n * The fields:\n * - `id` — stable identifier of the form `<pack>/<purpose>/<version>`,\n * e.g. `vaultsfyi/risk-envelope/v1`. Used for telemetry\n * and for cross-referencing the `policy_metadata.json`.\n * - `paramsSchema` — zod schema enforced at curator setup time when the\n * pack is bound to a `NewtonPolicyData`.\n * - `wasmArgsSchema` — zod schema enforced per call when the SDK builds the\n * intent and forwards `wasmArgs` to the gateway.\n * - `secretsSchema` — zod schema enforced at upload-time. Validates the\n * shape of the secrets the operator stores in the AVS.\n *\n * Encoding is *not* a per-pack concern. The on-chain `policyParams` byte\n * format is a Newton-protocol invariant — UTF-8 JSON, sorted keys —\n * implemented once in this package as `encodePolicyParams` /\n * `decodePolicyParams`. See `./encoding.ts`. Earlier shapes of this\n * interface required each pack to ship its own `encodeParams` /\n * `decodeParams`; that structurally invited drift (vaultsfyi@0.2.0 shipped\n * ABI bytes against an AVS that reads `serde_json::from_str`, breaking\n * every call). The interface now leaves byte-format to the protocol.\n *\n * - `prepareQuery` — optional. When present, the SDK invokes it on every\n * call to gather chain-state freshness inputs. Packs\n * that don't need this (e.g. KYC-only packs) omit it.\n * The optional second `options` argument is a\n * pack-typed escape hatch for per-call overrides —\n * e.g. VaultsFYI's `previousAllocationHash` for\n * freshness binding. Each concrete pack narrows it\n * via its own `prepareQuery` signature; the shared\n * interface keeps it `unknown` so the SDK can\n * forward it verbatim.\n * - `deployments` — `chainId → Deployment` map sliced from the upstream\n * `deployments.json` for this pack only. Typed as\n * `Partial<Record<ChainId, Deployment>>` so callers\n * must handle `undefined` for unsupported chains\n * rather than silently reading `.policy` off nothing.\n * Use `getDeployment(pack, chainId)` from this package\n * for the safe lookup.\n * - `metadata` — static identity from the pack's `policy_metadata.json`.\n */\nexport interface PolicyPack<TParams, TWasmArgs, TSecrets> {\n\treadonly id: string;\n\treadonly paramsSchema: z.ZodType<TParams>;\n\treadonly wasmArgsSchema: z.ZodType<TWasmArgs>;\n\treadonly secretsSchema: z.ZodType<TSecrets>;\n\tprepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;\n\treadonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;\n\treadonly metadata: {\n\t\treadonly name: string;\n\t\treadonly version: string;\n\t\treadonly description: string;\n\t\treadonly author?: string;\n\t\treadonly link?: string;\n\t};\n}\n\n/**\n * Safe lookup helper. Returns the `Deployment` for `chainId` if the pack is\n * deployed on that chain, or throws `UnsupportedChainError` with the list of\n * chain ids the pack is known to support. Use this at every SDK callsite that\n * reads `pack.deployments[chainId]` so unsupported-chain failures surface\n * immediately rather than as `undefined.policy` further down.\n */\nexport function getDeployment<TParams, TWasmArgs, TSecrets>(\n\tpack: PolicyPack<TParams, TWasmArgs, TSecrets>,\n\tchainId: ChainId,\n): Deployment {\n\tconst deployment = pack.deployments[chainId];\n\tif (!deployment) {\n\t\tconst supported = Object.keys(pack.deployments).sort().join(\", \") || \"(none)\";\n\t\tthrow new UnsupportedChainError(\n\t\t\t`Pack \\`${pack.id}\\` is not deployed on chain ${chainId}. Supported: ${supported}.`,\n\t\t\tpack.id,\n\t\t\tchainId,\n\t\t\tObject.keys(pack.deployments),\n\t\t);\n\t}\n\treturn deployment;\n}\n\n/**\n * Thrown by `getDeployment` when a pack is asked for a chain it isn't\n * deployed on. SDK consumers can catch this specifically to surface a\n * curator-friendly error rather than a `TypeError: Cannot read property\n * 'policy' of undefined`.\n */\nexport class UnsupportedChainError extends Error {\n\toverride readonly name = \"UnsupportedChainError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly packId: string,\n\t\treadonly chainId: ChainId,\n\t\treadonly supportedChainIds: ReadonlyArray<ChainId>,\n\t) {\n\t\tsuper(message);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,kBAA4C;AAa5C,SAAS,aAAa,OAAyB;AAC9C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,YAAY;AACvD,MAAI,SAAS,OAAO,UAAU,UAAU;AACvC,UAAM,MAAM;AACZ,UAAM,SAAkC,CAAC;AACzC,eAAW,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK,GAAG;AAC1C,aAAO,GAAG,IAAI,aAAa,IAAI,GAAG,CAAC;AAAA,IACpC;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAQO,SAAS,mBACf,MACA,QACM;AACN,QAAM,YAAY,KAAK,aAAa,MAAM,MAAM;AAChD,aAAO,mBAAM,KAAK,UAAU,aAAa,SAAS,CAAC,CAAC;AACrD;AAYO,SAAS,mBACf,MACA,SACI;AACJ,QAAM,OAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,WAAO,wBAAW,OAAO,CAAC;AACjF,SAAO,KAAK,aAAa,MAAM,KAAK,MAAM,IAAI,CAAC;AAChD;;;AC+CO,SAAS,cACf,MACA,SACa;AACb,QAAM,aAAa,KAAK,YAAY,OAAO;AAC3C,MAAI,CAAC,YAAY;AAChB,UAAM,YAAY,OAAO,KAAK,KAAK,WAAW,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK;AACrE,UAAM,IAAI;AAAA,MACT,UAAU,KAAK,EAAE,+BAA+B,OAAO,gBAAgB,SAAS;AAAA,MAChF,KAAK;AAAA,MACL;AAAA,MACA,OAAO,KAAK,KAAK,WAAW;AAAA,IAC7B;AAAA,EACD;AACA,SAAO;AACR;AAQO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAEhD,YACC,SACS,QACA,SACA,mBACR;AACD,UAAM,OAAO;AAJJ;AACA;AACA;AAAA,EAGV;AAAA,EALU;AAAA,EACA;AAAA,EACA;AAAA,EALQ,OAAO;AAS1B;","names":[]}
package/dist/index.d.cts CHANGED
@@ -39,6 +39,29 @@ interface Deployment {
39
39
  readonly notes?: string;
40
40
  }
41
41
 
42
+ /**
43
+ * Encode a pack's params for on-chain storage. Validates against the pack's
44
+ * `paramsSchema` so a curator typo throws here rather than silently writing
45
+ * AVS-rejecting bytes. Returns `Hex` so it drops directly into a viem
46
+ * `setPolicy(bytes)` call.
47
+ */
48
+ declare function encodePolicyParams<T>(pack: {
49
+ readonly paramsSchema: z.ZodType<T>;
50
+ }, params: T): Hex;
51
+ /**
52
+ * Decode `policyParams` bytes read from `getPolicyConfig().policyParams` back
53
+ * into the pack's typed params shape. Revalidates against `paramsSchema` so a
54
+ * stale or corrupted on-chain blob throws at the SDK boundary rather than
55
+ * yielding a partially-valid object that crashes deeper in the call.
56
+ *
57
+ * `fatal: true` matches AVS-side `String::from_utf8` behavior — invalid UTF-8
58
+ * throws here rather than silently becoming U+FFFD and diverging from a path
59
+ * the AVS would reject.
60
+ */
61
+ declare function decodePolicyParams<T>(pack: {
62
+ readonly paramsSchema: z.ZodType<T>;
63
+ }, encoded: Hex): T;
64
+
42
65
  /**
43
66
  * Inputs that a pack's `prepareQuery` reads at intent-build time.
44
67
  *
@@ -84,10 +107,16 @@ interface PrepareQueryResult<TWasmArgs> {
84
107
  * intent and forwards `wasmArgs` to the gateway.
85
108
  * - `secretsSchema` — zod schema enforced at upload-time. Validates the
86
109
  * shape of the secrets the operator stores in the AVS.
87
- * - `encodeParams` / `decodeParams` — ABI round-trip for the on-chain
88
- * `policyParams` bytes. Must round-trip cleanly so the
89
- * SDK can read the on-chain value back and confirm it
90
- * matches the curator's intended config.
110
+ *
111
+ * Encoding is *not* a per-pack concern. The on-chain `policyParams` byte
112
+ * format is a Newton-protocol invariant UTF-8 JSON, sorted keys —
113
+ * implemented once in this package as `encodePolicyParams` /
114
+ * `decodePolicyParams`. See `./encoding.ts`. Earlier shapes of this
115
+ * interface required each pack to ship its own `encodeParams` /
116
+ * `decodeParams`; that structurally invited drift (vaultsfyi@0.2.0 shipped
117
+ * ABI bytes against an AVS that reads `serde_json::from_str`, breaking
118
+ * every call). The interface now leaves byte-format to the protocol.
119
+ *
91
120
  * - `prepareQuery` — optional. When present, the SDK invokes it on every
92
121
  * call to gather chain-state freshness inputs. Packs
93
122
  * that don't need this (e.g. KYC-only packs) omit it.
@@ -112,8 +141,6 @@ interface PolicyPack<TParams, TWasmArgs, TSecrets> {
112
141
  readonly paramsSchema: z.ZodType<TParams>;
113
142
  readonly wasmArgsSchema: z.ZodType<TWasmArgs>;
114
143
  readonly secretsSchema: z.ZodType<TSecrets>;
115
- encodeParams(params: TParams): Hex;
116
- decodeParams(encoded: Hex): TParams;
117
144
  prepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;
118
145
  readonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;
119
146
  readonly metadata: {
@@ -146,4 +173,4 @@ declare class UnsupportedChainError extends Error {
146
173
  constructor(message: string, packId: string, chainId: ChainId, supportedChainIds: ReadonlyArray<ChainId>);
147
174
  }
148
175
 
149
- export { type ChainId, type Deployment, type PolicyPack, type PrepareQueryArgs, type PrepareQueryResult, UnsupportedChainError, getDeployment };
176
+ export { type ChainId, type Deployment, type PolicyPack, type PrepareQueryArgs, type PrepareQueryResult, UnsupportedChainError, decodePolicyParams, encodePolicyParams, getDeployment };
package/dist/index.d.ts CHANGED
@@ -39,6 +39,29 @@ interface Deployment {
39
39
  readonly notes?: string;
40
40
  }
41
41
 
42
+ /**
43
+ * Encode a pack's params for on-chain storage. Validates against the pack's
44
+ * `paramsSchema` so a curator typo throws here rather than silently writing
45
+ * AVS-rejecting bytes. Returns `Hex` so it drops directly into a viem
46
+ * `setPolicy(bytes)` call.
47
+ */
48
+ declare function encodePolicyParams<T>(pack: {
49
+ readonly paramsSchema: z.ZodType<T>;
50
+ }, params: T): Hex;
51
+ /**
52
+ * Decode `policyParams` bytes read from `getPolicyConfig().policyParams` back
53
+ * into the pack's typed params shape. Revalidates against `paramsSchema` so a
54
+ * stale or corrupted on-chain blob throws at the SDK boundary rather than
55
+ * yielding a partially-valid object that crashes deeper in the call.
56
+ *
57
+ * `fatal: true` matches AVS-side `String::from_utf8` behavior — invalid UTF-8
58
+ * throws here rather than silently becoming U+FFFD and diverging from a path
59
+ * the AVS would reject.
60
+ */
61
+ declare function decodePolicyParams<T>(pack: {
62
+ readonly paramsSchema: z.ZodType<T>;
63
+ }, encoded: Hex): T;
64
+
42
65
  /**
43
66
  * Inputs that a pack's `prepareQuery` reads at intent-build time.
44
67
  *
@@ -84,10 +107,16 @@ interface PrepareQueryResult<TWasmArgs> {
84
107
  * intent and forwards `wasmArgs` to the gateway.
85
108
  * - `secretsSchema` — zod schema enforced at upload-time. Validates the
86
109
  * shape of the secrets the operator stores in the AVS.
87
- * - `encodeParams` / `decodeParams` — ABI round-trip for the on-chain
88
- * `policyParams` bytes. Must round-trip cleanly so the
89
- * SDK can read the on-chain value back and confirm it
90
- * matches the curator's intended config.
110
+ *
111
+ * Encoding is *not* a per-pack concern. The on-chain `policyParams` byte
112
+ * format is a Newton-protocol invariant UTF-8 JSON, sorted keys —
113
+ * implemented once in this package as `encodePolicyParams` /
114
+ * `decodePolicyParams`. See `./encoding.ts`. Earlier shapes of this
115
+ * interface required each pack to ship its own `encodeParams` /
116
+ * `decodeParams`; that structurally invited drift (vaultsfyi@0.2.0 shipped
117
+ * ABI bytes against an AVS that reads `serde_json::from_str`, breaking
118
+ * every call). The interface now leaves byte-format to the protocol.
119
+ *
91
120
  * - `prepareQuery` — optional. When present, the SDK invokes it on every
92
121
  * call to gather chain-state freshness inputs. Packs
93
122
  * that don't need this (e.g. KYC-only packs) omit it.
@@ -112,8 +141,6 @@ interface PolicyPack<TParams, TWasmArgs, TSecrets> {
112
141
  readonly paramsSchema: z.ZodType<TParams>;
113
142
  readonly wasmArgsSchema: z.ZodType<TWasmArgs>;
114
143
  readonly secretsSchema: z.ZodType<TSecrets>;
115
- encodeParams(params: TParams): Hex;
116
- decodeParams(encoded: Hex): TParams;
117
144
  prepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;
118
145
  readonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;
119
146
  readonly metadata: {
@@ -146,4 +173,4 @@ declare class UnsupportedChainError extends Error {
146
173
  constructor(message: string, packId: string, chainId: ChainId, supportedChainIds: ReadonlyArray<ChainId>);
147
174
  }
148
175
 
149
- export { type ChainId, type Deployment, type PolicyPack, type PrepareQueryArgs, type PrepareQueryResult, UnsupportedChainError, getDeployment };
176
+ export { type ChainId, type Deployment, type PolicyPack, type PrepareQueryArgs, type PrepareQueryResult, UnsupportedChainError, decodePolicyParams, encodePolicyParams, getDeployment };
package/dist/index.js CHANGED
@@ -1,3 +1,26 @@
1
+ // src/encoding.ts
2
+ import { hexToBytes, toHex } from "viem";
3
+ function sortKeysDeep(value) {
4
+ if (Array.isArray(value)) return value.map(sortKeysDeep);
5
+ if (value && typeof value === "object") {
6
+ const obj = value;
7
+ const sorted = {};
8
+ for (const key of Object.keys(obj).sort()) {
9
+ sorted[key] = sortKeysDeep(obj[key]);
10
+ }
11
+ return sorted;
12
+ }
13
+ return value;
14
+ }
15
+ function encodePolicyParams(pack, params) {
16
+ const validated = pack.paramsSchema.parse(params);
17
+ return toHex(JSON.stringify(sortKeysDeep(validated)));
18
+ }
19
+ function decodePolicyParams(pack, encoded) {
20
+ const json = new TextDecoder("utf-8", { fatal: true }).decode(hexToBytes(encoded));
21
+ return pack.paramsSchema.parse(JSON.parse(json));
22
+ }
23
+
1
24
  // src/pack.ts
2
25
  function getDeployment(pack, chainId) {
3
26
  const deployment = pack.deployments[chainId];
@@ -26,6 +49,8 @@ var UnsupportedChainError = class extends Error {
26
49
  };
27
50
  export {
28
51
  UnsupportedChainError,
52
+ decodePolicyParams,
53
+ encodePolicyParams,
29
54
  getDeployment
30
55
  };
31
56
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/pack.ts"],"sourcesContent":["import type { Address, Hex, PublicClient } from \"viem\";\nimport type { z } from \"zod\";\nimport type { ChainId, Deployment } from \"./deployment\";\n\n/**\n * Inputs that a pack's `prepareQuery` reads at intent-build time.\n *\n * The Shield SDK passes a viem `PublicClient` (so the pack can read on-chain\n * state) and the vault address the curator is acting on. Packs that don't\n * need on-chain state can ignore both — `prepareQuery` is optional.\n */\nexport interface PrepareQueryArgs {\n\treadonly publicClient: PublicClient;\n\treadonly vault: Address;\n}\n\n/**\n * `wasmArgs` payload (untyped at this layer; each pack narrows it via its own\n * `WasmArgsSchema`) plus an optional pre-image hash for binding the AVS-side\n * evaluation to a specific on-chain state. VaultsFYI uses this to bind the\n * evaluation to a `keccak(supplyQueue)` snapshot so the policy can reject\n * attestations whose underlying allocation has shifted between intent build\n * and on-chain submission.\n */\nexport interface PrepareQueryResult<TWasmArgs> {\n\treadonly wasmArgs: TWasmArgs;\n\treadonly freshnessHash?: Hex;\n}\n\n/**\n * Canonical typed contract every published `@newton-xyz/policy-pack-<name>`\n * package implements. `@newton-xyz/newton-shield-sdk`'s `createShield(...)`\n * accepts `PolicyPack<P, W, S>` as the curator's pack argument.\n *\n * Type parameters:\n * - `TParams` — the shape stored on-chain in `NewtonPolicyData.policyParams`\n * (e.g. risk envelope thresholds for VaultsFYI).\n * - `TWasmArgs` — the shape passed to the policy's WASM oracle at evaluation\n * time (e.g. `{ vault, network, lastKnownAllocationHash }`).\n * - `TSecrets` — required API credentials uploaded before any run/sim.\n *\n * The fields:\n * - `id` — stable identifier of the form `<pack>/<purpose>/<version>`,\n * e.g. `vaultsfyi/risk-envelope/v1`. Used for telemetry\n * and for cross-referencing the `policy_metadata.json`.\n * - `paramsSchema` — zod schema enforced at curator setup time when the\n * pack is bound to a `NewtonPolicyData`.\n * - `wasmArgsSchema` — zod schema enforced per call when the SDK builds the\n * intent and forwards `wasmArgs` to the gateway.\n * - `secretsSchema` — zod schema enforced at upload-time. Validates the\n * shape of the secrets the operator stores in the AVS.\n * - `encodeParams` / `decodeParams` ABI round-trip for the on-chain\n * `policyParams` bytes. Must round-trip cleanly so the\n * SDK can read the on-chain value back and confirm it\n * matches the curator's intended config.\n * - `prepareQuery` — optional. When present, the SDK invokes it on every\n * call to gather chain-state freshness inputs. Packs\n * that don't need this (e.g. KYC-only packs) omit it.\n * The optional second `options` argument is a\n * pack-typed escape hatch for per-call overrides —\n * e.g. VaultsFYI's `previousAllocationHash` for\n * freshness binding. Each concrete pack narrows it\n * via its own `prepareQuery` signature; the shared\n * interface keeps it `unknown` so the SDK can\n * forward it verbatim.\n * - `deployments` — `chainId → Deployment` map sliced from the upstream\n * `deployments.json` for this pack only. Typed as\n * `Partial<Record<ChainId, Deployment>>` so callers\n * must handle `undefined` for unsupported chains\n * rather than silently reading `.policy` off nothing.\n * Use `getDeployment(pack, chainId)` from this package\n * for the safe lookup.\n * - `metadata` — static identity from the pack's `policy_metadata.json`.\n */\nexport interface PolicyPack<TParams, TWasmArgs, TSecrets> {\n\treadonly id: string;\n\treadonly paramsSchema: z.ZodType<TParams>;\n\treadonly wasmArgsSchema: z.ZodType<TWasmArgs>;\n\treadonly secretsSchema: z.ZodType<TSecrets>;\n\tencodeParams(params: TParams): Hex;\n\tdecodeParams(encoded: Hex): TParams;\n\tprepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;\n\treadonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;\n\treadonly metadata: {\n\t\treadonly name: string;\n\t\treadonly version: string;\n\t\treadonly description: string;\n\t\treadonly author?: string;\n\t\treadonly link?: string;\n\t};\n}\n\n/**\n * Safe lookup helper. Returns the `Deployment` for `chainId` if the pack is\n * deployed on that chain, or throws `UnsupportedChainError` with the list of\n * chain ids the pack is known to support. Use this at every SDK callsite that\n * reads `pack.deployments[chainId]` so unsupported-chain failures surface\n * immediately rather than as `undefined.policy` further down.\n */\nexport function getDeployment<TParams, TWasmArgs, TSecrets>(\n\tpack: PolicyPack<TParams, TWasmArgs, TSecrets>,\n\tchainId: ChainId,\n): Deployment {\n\tconst deployment = pack.deployments[chainId];\n\tif (!deployment) {\n\t\tconst supported = Object.keys(pack.deployments).sort().join(\", \") || \"(none)\";\n\t\tthrow new UnsupportedChainError(\n\t\t\t`Pack \\`${pack.id}\\` is not deployed on chain ${chainId}. Supported: ${supported}.`,\n\t\t\tpack.id,\n\t\t\tchainId,\n\t\t\tObject.keys(pack.deployments),\n\t\t);\n\t}\n\treturn deployment;\n}\n\n/**\n * Thrown by `getDeployment` when a pack is asked for a chain it isn't\n * deployed on. SDK consumers can catch this specifically to surface a\n * curator-friendly error rather than a `TypeError: Cannot read property\n * 'policy' of undefined`.\n */\nexport class UnsupportedChainError extends Error {\n\toverride readonly name = \"UnsupportedChainError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly packId: string,\n\t\treadonly chainId: ChainId,\n\t\treadonly supportedChainIds: ReadonlyArray<ChainId>,\n\t) {\n\t\tsuper(message);\n\t}\n}\n"],"mappings":";AAmGO,SAAS,cACf,MACA,SACa;AACb,QAAM,aAAa,KAAK,YAAY,OAAO;AAC3C,MAAI,CAAC,YAAY;AAChB,UAAM,YAAY,OAAO,KAAK,KAAK,WAAW,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK;AACrE,UAAM,IAAI;AAAA,MACT,UAAU,KAAK,EAAE,+BAA+B,OAAO,gBAAgB,SAAS;AAAA,MAChF,KAAK;AAAA,MACL;AAAA,MACA,OAAO,KAAK,KAAK,WAAW;AAAA,IAC7B;AAAA,EACD;AACA,SAAO;AACR;AAQO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAEhD,YACC,SACS,QACA,SACA,mBACR;AACD,UAAM,OAAO;AAJJ;AACA;AACA;AAAA,EAGV;AAAA,EALU;AAAA,EACA;AAAA,EACA;AAAA,EALQ,OAAO;AAS1B;","names":[]}
1
+ {"version":3,"sources":["../src/encoding.ts","../src/pack.ts"],"sourcesContent":["import { type Hex, hexToBytes, toHex } from \"viem\";\nimport type { z } from \"zod\";\n\n/**\n * The on-chain `policyParams` byte format is a Newton-protocol invariant. The\n * AVS host reads it as `String::from_utf8 → serde_json::from_str` (see\n * `newton-prover-avs/crates/core/src/common/task.rs:402-408`); the SDK must\n * therefore write **UTF-8 JSON**. Keys are sorted recursively so two\n * semantically-equal params objects always produce byte-identical output —\n * the SDK's `verifyPolicyBinding` does a byte-equality check against\n * `getPolicyConfig().policyParams`, which would otherwise depend on JS\n * `JSON.stringify` insertion order.\n */\nfunction sortKeysDeep(value: unknown): unknown {\n\tif (Array.isArray(value)) return value.map(sortKeysDeep);\n\tif (value && typeof value === \"object\") {\n\t\tconst obj = value as Record<string, unknown>;\n\t\tconst sorted: Record<string, unknown> = {};\n\t\tfor (const key of Object.keys(obj).sort()) {\n\t\t\tsorted[key] = sortKeysDeep(obj[key]);\n\t\t}\n\t\treturn sorted;\n\t}\n\treturn value;\n}\n\n/**\n * Encode a pack's params for on-chain storage. Validates against the pack's\n * `paramsSchema` so a curator typo throws here rather than silently writing\n * AVS-rejecting bytes. Returns `Hex` so it drops directly into a viem\n * `setPolicy(bytes)` call.\n */\nexport function encodePolicyParams<T>(\n\tpack: { readonly paramsSchema: z.ZodType<T> },\n\tparams: T,\n): Hex {\n\tconst validated = pack.paramsSchema.parse(params);\n\treturn toHex(JSON.stringify(sortKeysDeep(validated)));\n}\n\n/**\n * Decode `policyParams` bytes read from `getPolicyConfig().policyParams` back\n * into the pack's typed params shape. Revalidates against `paramsSchema` so a\n * stale or corrupted on-chain blob throws at the SDK boundary rather than\n * yielding a partially-valid object that crashes deeper in the call.\n *\n * `fatal: true` matches AVS-side `String::from_utf8` behavior — invalid UTF-8\n * throws here rather than silently becoming U+FFFD and diverging from a path\n * the AVS would reject.\n */\nexport function decodePolicyParams<T>(\n\tpack: { readonly paramsSchema: z.ZodType<T> },\n\tencoded: Hex,\n): T {\n\tconst json = new TextDecoder(\"utf-8\", { fatal: true }).decode(hexToBytes(encoded));\n\treturn pack.paramsSchema.parse(JSON.parse(json));\n}\n","import type { Address, Hex, PublicClient } from \"viem\";\nimport type { z } from \"zod\";\nimport type { ChainId, Deployment } from \"./deployment\";\n\n/**\n * Inputs that a pack's `prepareQuery` reads at intent-build time.\n *\n * The Shield SDK passes a viem `PublicClient` (so the pack can read on-chain\n * state) and the vault address the curator is acting on. Packs that don't\n * need on-chain state can ignore both — `prepareQuery` is optional.\n */\nexport interface PrepareQueryArgs {\n\treadonly publicClient: PublicClient;\n\treadonly vault: Address;\n}\n\n/**\n * `wasmArgs` payload (untyped at this layer; each pack narrows it via its own\n * `WasmArgsSchema`) plus an optional pre-image hash for binding the AVS-side\n * evaluation to a specific on-chain state. VaultsFYI uses this to bind the\n * evaluation to a `keccak(supplyQueue)` snapshot so the policy can reject\n * attestations whose underlying allocation has shifted between intent build\n * and on-chain submission.\n */\nexport interface PrepareQueryResult<TWasmArgs> {\n\treadonly wasmArgs: TWasmArgs;\n\treadonly freshnessHash?: Hex;\n}\n\n/**\n * Canonical typed contract every published `@newton-xyz/policy-pack-<name>`\n * package implements. `@newton-xyz/newton-shield-sdk`'s `createShield(...)`\n * accepts `PolicyPack<P, W, S>` as the curator's pack argument.\n *\n * Type parameters:\n * - `TParams` — the shape stored on-chain in `NewtonPolicyData.policyParams`\n * (e.g. risk envelope thresholds for VaultsFYI).\n * - `TWasmArgs` — the shape passed to the policy's WASM oracle at evaluation\n * time (e.g. `{ vault, network, lastKnownAllocationHash }`).\n * - `TSecrets` — required API credentials uploaded before any run/sim.\n *\n * The fields:\n * - `id` — stable identifier of the form `<pack>/<purpose>/<version>`,\n * e.g. `vaultsfyi/risk-envelope/v1`. Used for telemetry\n * and for cross-referencing the `policy_metadata.json`.\n * - `paramsSchema` — zod schema enforced at curator setup time when the\n * pack is bound to a `NewtonPolicyData`.\n * - `wasmArgsSchema` — zod schema enforced per call when the SDK builds the\n * intent and forwards `wasmArgs` to the gateway.\n * - `secretsSchema` — zod schema enforced at upload-time. Validates the\n * shape of the secrets the operator stores in the AVS.\n *\n * Encoding is *not* a per-pack concern. The on-chain `policyParams` byte\n * format is a Newton-protocol invariant UTF-8 JSON, sorted keys —\n * implemented once in this package as `encodePolicyParams` /\n * `decodePolicyParams`. See `./encoding.ts`. Earlier shapes of this\n * interface required each pack to ship its own `encodeParams` /\n * `decodeParams`; that structurally invited drift (vaultsfyi@0.2.0 shipped\n * ABI bytes against an AVS that reads `serde_json::from_str`, breaking\n * every call). The interface now leaves byte-format to the protocol.\n *\n * - `prepareQuery` — optional. When present, the SDK invokes it on every\n * call to gather chain-state freshness inputs. Packs\n * that don't need this (e.g. KYC-only packs) omit it.\n * The optional second `options` argument is a\n * pack-typed escape hatch for per-call overrides —\n * e.g. VaultsFYI's `previousAllocationHash` for\n * freshness binding. Each concrete pack narrows it\n * via its own `prepareQuery` signature; the shared\n * interface keeps it `unknown` so the SDK can\n * forward it verbatim.\n * - `deployments` — `chainId → Deployment` map sliced from the upstream\n * `deployments.json` for this pack only. Typed as\n * `Partial<Record<ChainId, Deployment>>` so callers\n * must handle `undefined` for unsupported chains\n * rather than silently reading `.policy` off nothing.\n * Use `getDeployment(pack, chainId)` from this package\n * for the safe lookup.\n * - `metadata` — static identity from the pack's `policy_metadata.json`.\n */\nexport interface PolicyPack<TParams, TWasmArgs, TSecrets> {\n\treadonly id: string;\n\treadonly paramsSchema: z.ZodType<TParams>;\n\treadonly wasmArgsSchema: z.ZodType<TWasmArgs>;\n\treadonly secretsSchema: z.ZodType<TSecrets>;\n\tprepareQuery?(args: PrepareQueryArgs, options?: unknown): Promise<PrepareQueryResult<TWasmArgs>>;\n\treadonly deployments: Readonly<Partial<Record<ChainId, Deployment>>>;\n\treadonly metadata: {\n\t\treadonly name: string;\n\t\treadonly version: string;\n\t\treadonly description: string;\n\t\treadonly author?: string;\n\t\treadonly link?: string;\n\t};\n}\n\n/**\n * Safe lookup helper. Returns the `Deployment` for `chainId` if the pack is\n * deployed on that chain, or throws `UnsupportedChainError` with the list of\n * chain ids the pack is known to support. Use this at every SDK callsite that\n * reads `pack.deployments[chainId]` so unsupported-chain failures surface\n * immediately rather than as `undefined.policy` further down.\n */\nexport function getDeployment<TParams, TWasmArgs, TSecrets>(\n\tpack: PolicyPack<TParams, TWasmArgs, TSecrets>,\n\tchainId: ChainId,\n): Deployment {\n\tconst deployment = pack.deployments[chainId];\n\tif (!deployment) {\n\t\tconst supported = Object.keys(pack.deployments).sort().join(\", \") || \"(none)\";\n\t\tthrow new UnsupportedChainError(\n\t\t\t`Pack \\`${pack.id}\\` is not deployed on chain ${chainId}. Supported: ${supported}.`,\n\t\t\tpack.id,\n\t\t\tchainId,\n\t\t\tObject.keys(pack.deployments),\n\t\t);\n\t}\n\treturn deployment;\n}\n\n/**\n * Thrown by `getDeployment` when a pack is asked for a chain it isn't\n * deployed on. SDK consumers can catch this specifically to surface a\n * curator-friendly error rather than a `TypeError: Cannot read property\n * 'policy' of undefined`.\n */\nexport class UnsupportedChainError extends Error {\n\toverride readonly name = \"UnsupportedChainError\";\n\tconstructor(\n\t\tmessage: string,\n\t\treadonly packId: string,\n\t\treadonly chainId: ChainId,\n\t\treadonly supportedChainIds: ReadonlyArray<ChainId>,\n\t) {\n\t\tsuper(message);\n\t}\n}\n"],"mappings":";AAAA,SAAmB,YAAY,aAAa;AAa5C,SAAS,aAAa,OAAyB;AAC9C,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,YAAY;AACvD,MAAI,SAAS,OAAO,UAAU,UAAU;AACvC,UAAM,MAAM;AACZ,UAAM,SAAkC,CAAC;AACzC,eAAW,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK,GAAG;AAC1C,aAAO,GAAG,IAAI,aAAa,IAAI,GAAG,CAAC;AAAA,IACpC;AACA,WAAO;AAAA,EACR;AACA,SAAO;AACR;AAQO,SAAS,mBACf,MACA,QACM;AACN,QAAM,YAAY,KAAK,aAAa,MAAM,MAAM;AAChD,SAAO,MAAM,KAAK,UAAU,aAAa,SAAS,CAAC,CAAC;AACrD;AAYO,SAAS,mBACf,MACA,SACI;AACJ,QAAM,OAAO,IAAI,YAAY,SAAS,EAAE,OAAO,KAAK,CAAC,EAAE,OAAO,WAAW,OAAO,CAAC;AACjF,SAAO,KAAK,aAAa,MAAM,KAAK,MAAM,IAAI,CAAC;AAChD;;;AC+CO,SAAS,cACf,MACA,SACa;AACb,QAAM,aAAa,KAAK,YAAY,OAAO;AAC3C,MAAI,CAAC,YAAY;AAChB,UAAM,YAAY,OAAO,KAAK,KAAK,WAAW,EAAE,KAAK,EAAE,KAAK,IAAI,KAAK;AACrE,UAAM,IAAI;AAAA,MACT,UAAU,KAAK,EAAE,+BAA+B,OAAO,gBAAgB,SAAS;AAAA,MAChF,KAAK;AAAA,MACL;AAAA,MACA,OAAO,KAAK,KAAK,WAAW;AAAA,IAC7B;AAAA,EACD;AACA,SAAO;AACR;AAQO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAEhD,YACC,SACS,QACA,SACA,mBACR;AACD,UAAM,OAAO;AAJJ;AACA;AACA;AAAA,EAGV;AAAA,EALU;AAAA,EACA;AAAA,EACA;AAAA,EALQ,OAAO;AAS1B;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newton-xyz/policy-pack-shared",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Shared TypeScript contract for Newton policy packs. Defines the PolicyPack<Params, WasmArgs, Secrets> interface that @newton-xyz/newton-shield-sdk consumes.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Newton Protocol <https://x.com/newton_xyz> (https://newton.xyz)",
@@ -47,6 +47,7 @@
47
47
  },
48
48
  "devDependencies": {
49
49
  "tsup": "^8.5.1",
50
+ "tsx": "^4.19.0",
50
51
  "typescript": "^5.5.0",
51
52
  "viem": "^2.0.0",
52
53
  "zod": "^3.23.0"
@@ -55,6 +56,6 @@
55
56
  "build": "tsup",
56
57
  "dev": "tsup --watch",
57
58
  "typecheck": "tsc --noEmit",
58
- "test": "echo 'no tests yet'"
59
+ "test": "node --import tsx --test src/*.test.ts"
59
60
  }
60
61
  }