@opendatalabs/vana-sdk 3.1.0 → 3.2.0-canary.88d802d

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.
Files changed (97) hide show
  1. package/README.md +2 -1
  2. package/dist/account/personal-server-lite-owner-binding.cjs +81 -0
  3. package/dist/account/personal-server-lite-owner-binding.cjs.map +1 -0
  4. package/dist/account/personal-server-lite-owner-binding.d.ts +30 -0
  5. package/dist/account/personal-server-lite-owner-binding.js +59 -0
  6. package/dist/account/personal-server-lite-owner-binding.js.map +1 -0
  7. package/dist/account/personal-server-lite-owner-binding.test.d.ts +1 -0
  8. package/dist/account/personal-server-registration.cjs +263 -0
  9. package/dist/account/personal-server-registration.cjs.map +1 -0
  10. package/dist/account/personal-server-registration.d.ts +66 -0
  11. package/dist/account/personal-server-registration.js +240 -0
  12. package/dist/account/personal-server-registration.js.map +1 -0
  13. package/dist/account/personal-server-registration.test.d.ts +1 -0
  14. package/dist/auth/errors.js +1 -1
  15. package/dist/auth/oauth-client.js +2 -2
  16. package/dist/auth/web3-signed-builder.js +1 -1
  17. package/dist/auth/web3-signed.js +3 -3
  18. package/dist/browser.js +1 -1
  19. package/dist/chains/definitions.js +1 -1
  20. package/dist/chains/index.js +1 -1
  21. package/dist/chains.browser.js +1 -1
  22. package/dist/chains.js +1 -1
  23. package/dist/chains.node.js +1 -1
  24. package/dist/contracts/contractController.js +4 -4
  25. package/dist/core/client.js +1 -1
  26. package/dist/crypto/ecies/base.js +3 -3
  27. package/dist/crypto/ecies/browser.js +1 -1
  28. package/dist/crypto/ecies/index.js +1 -1
  29. package/dist/crypto/ecies/interface.js +1 -1
  30. package/dist/crypto/ecies/node.js +1 -1
  31. package/dist/crypto/services/WalletKeyEncryptionService.js +1 -1
  32. package/dist/generated/abi/index.js +26 -26
  33. package/dist/index.browser.d.ts +8 -3
  34. package/dist/index.browser.js +706 -72
  35. package/dist/index.browser.js.map +4 -4
  36. package/dist/index.node.cjs +733 -73
  37. package/dist/index.node.cjs.map +4 -4
  38. package/dist/index.node.d.ts +8 -3
  39. package/dist/index.node.js +706 -72
  40. package/dist/index.node.js.map +4 -4
  41. package/dist/node.js +1 -1
  42. package/dist/platform/browser-only.js +1 -1
  43. package/dist/platform/browser-safe.js +1 -1
  44. package/dist/platform/browser.js +6 -6
  45. package/dist/platform/index.js +4 -4
  46. package/dist/platform/node.js +8 -8
  47. package/dist/platform/utils.js +2 -2
  48. package/dist/platform.browser.js +3 -3
  49. package/dist/platform.js +4 -4
  50. package/dist/platform.node.js +4 -4
  51. package/dist/protocol/eip712.cjs +58 -3
  52. package/dist/protocol/eip712.cjs.map +1 -1
  53. package/dist/protocol/eip712.d.ts +98 -7
  54. package/dist/protocol/eip712.js +52 -3
  55. package/dist/protocol/eip712.js.map +1 -1
  56. package/dist/protocol/escrow-deposit.cjs +89 -0
  57. package/dist/protocol/escrow-deposit.cjs.map +1 -0
  58. package/dist/protocol/escrow-deposit.d.ts +47 -0
  59. package/dist/protocol/escrow-deposit.js +60 -0
  60. package/dist/protocol/escrow-deposit.js.map +1 -0
  61. package/dist/protocol/escrow-deposit.test.d.ts +1 -0
  62. package/dist/protocol/escrow-flow.test.d.ts +21 -0
  63. package/dist/protocol/gateway.cjs +124 -3
  64. package/dist/protocol/gateway.cjs.map +1 -1
  65. package/dist/protocol/gateway.d.ts +196 -16
  66. package/dist/protocol/gateway.js +124 -3
  67. package/dist/protocol/gateway.js.map +1 -1
  68. package/dist/protocol/grants.cjs +24 -64
  69. package/dist/protocol/grants.cjs.map +1 -1
  70. package/dist/protocol/grants.d.ts +6 -13
  71. package/dist/protocol/grants.js +25 -64
  72. package/dist/protocol/grants.js.map +1 -1
  73. package/dist/protocol/personal-server-lite-owner-binding.cjs +93 -0
  74. package/dist/protocol/personal-server-lite-owner-binding.cjs.map +1 -0
  75. package/dist/protocol/personal-server-lite-owner-binding.d.ts +44 -0
  76. package/dist/protocol/personal-server-lite-owner-binding.js +65 -0
  77. package/dist/protocol/personal-server-lite-owner-binding.js.map +1 -0
  78. package/dist/protocol/personal-server-lite-owner-binding.test.d.ts +1 -0
  79. package/dist/protocol/personal-server-registration.cjs +122 -0
  80. package/dist/protocol/personal-server-registration.cjs.map +1 -0
  81. package/dist/protocol/personal-server-registration.d.ts +62 -0
  82. package/dist/protocol/personal-server-registration.js +97 -0
  83. package/dist/protocol/personal-server-registration.js.map +1 -0
  84. package/dist/protocol/personal-server-registration.test.d.ts +1 -0
  85. package/dist/storage/default.js +1 -1
  86. package/dist/storage/index.js +10 -10
  87. package/dist/storage/manager.js +1 -1
  88. package/dist/storage/providers/callback-storage.js +1 -1
  89. package/dist/storage/providers/dropbox.js +1 -1
  90. package/dist/storage/providers/google-drive.js +1 -1
  91. package/dist/storage/providers/ipfs.js +2 -2
  92. package/dist/storage/providers/pinata.js +1 -1
  93. package/dist/storage/providers/r2.js +1 -1
  94. package/dist/storage/providers/vana-storage.js +2 -2
  95. package/dist/types/index.js +2 -2
  96. package/dist/types.js +1 -1
  97. package/package.json +6 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/protocol/grants.ts"],"sourcesContent":["import { verifyTypedData } from \"viem\";\nimport {\n GRANT_REGISTRATION_TYPES,\n grantRegistrationDomain,\n type DataPortabilityGatewayConfig,\n} from \"./eip712\";\n\nexport interface DataPortabilityGrantPayload {\n user?: `0x${string}`;\n builder?: `0x${string}`;\n scopes: string[];\n expiresAt: number;\n nonce?: number;\n}\n\nexport interface VerifyGrantRegistrationInput {\n gatewayConfig: DataPortabilityGatewayConfig;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n grant: string;\n fileIds?: Array<string | number | bigint>;\n signature: `0x${string}`;\n nowSeconds?: number;\n}\n\nexport type VerifyGrantRegistrationResult =\n | {\n valid: true;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n grant: string;\n payload: DataPortabilityGrantPayload;\n fileIds: string[];\n }\n | {\n valid: false;\n error: string;\n };\n\nfunction isHexString(value: unknown): value is `0x${string}` {\n return typeof value === \"string\" && value.startsWith(\"0x\");\n}\n\nexport function isDataPortabilityGatewayConfig(\n value: unknown,\n): value is DataPortabilityGatewayConfig {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n const config = value as Record<string, unknown>;\n const contracts = config[\"contracts\"];\n if (\n typeof config[\"chainId\"] !== \"number\" ||\n !Number.isInteger(config[\"chainId\"]) ||\n config[\"chainId\"] <= 0 ||\n contracts === null ||\n typeof contracts !== \"object\" ||\n Array.isArray(contracts)\n ) {\n return false;\n }\n const c = contracts as Record<string, unknown>;\n return (\n isHexString(c[\"dataRegistry\"]) &&\n isHexString(c[\"dataPortabilityPermissions\"]) &&\n isHexString(c[\"dataPortabilityServer\"]) &&\n isHexString(c[\"dataPortabilityGrantees\"])\n );\n}\n\nexport function parseGrantRegistrationPayload(\n grant: string,\n): DataPortabilityGrantPayload | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(grant);\n } catch {\n return null;\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return null;\n }\n const value = parsed as Record<string, unknown>;\n if (!Array.isArray(value[\"scopes\"]) || value[\"scopes\"].length === 0) {\n return null;\n }\n if (!value[\"scopes\"].every((scope) => typeof scope === \"string\")) {\n return null;\n }\n if (\n typeof value[\"expiresAt\"] !== \"number\" ||\n !Number.isFinite(value[\"expiresAt\"])\n ) {\n return null;\n }\n if (value[\"user\"] !== undefined && !isHexString(value[\"user\"])) {\n return null;\n }\n if (value[\"builder\"] !== undefined && !isHexString(value[\"builder\"])) {\n return null;\n }\n if (\n value[\"nonce\"] !== undefined &&\n (typeof value[\"nonce\"] !== \"number\" || !Number.isFinite(value[\"nonce\"]))\n ) {\n return null;\n }\n return {\n user: value[\"user\"] as `0x${string}` | undefined,\n builder: value[\"builder\"] as `0x${string}` | undefined,\n scopes: value[\"scopes\"] as string[],\n expiresAt: value[\"expiresAt\"],\n nonce: value[\"nonce\"] as number | undefined,\n };\n}\n\nfunction parseFileIds(fileIds: Array<string | number | bigint> | undefined): {\n values: bigint[];\n display: string[];\n} | null {\n try {\n const values = (fileIds ?? []).map((fileId) => BigInt(fileId));\n return {\n values,\n display: values.map((fileId) => fileId.toString()),\n };\n } catch {\n return null;\n }\n}\n\nexport async function verifyGrantRegistration(\n input: VerifyGrantRegistrationInput,\n): Promise<VerifyGrantRegistrationResult> {\n const payload = parseGrantRegistrationPayload(input.grant);\n if (!payload) {\n return {\n valid: false,\n error: \"Grant must be JSON with scopes and expiresAt\",\n };\n }\n\n const fileIds = parseFileIds(input.fileIds);\n if (!fileIds) {\n return { valid: false, error: \"fileIds must contain integer values\" };\n }\n\n let valid: boolean;\n try {\n valid = await verifyTypedData({\n address: input.grantorAddress,\n domain: grantRegistrationDomain(input.gatewayConfig),\n types: GRANT_REGISTRATION_TYPES,\n primaryType: \"GrantRegistration\",\n message: {\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n grant: input.grant,\n fileIds: fileIds.values,\n },\n signature: input.signature,\n });\n } catch {\n return { valid: false, error: \"EIP-712 signature verification failed\" };\n }\n\n if (!valid) {\n return { valid: false, error: \"Grant signature does not match grantor\" };\n }\n\n const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n if (payload.expiresAt > 0 && payload.expiresAt < nowSeconds) {\n return { valid: false, error: \"Grant has expired\" };\n }\n\n if (\n payload.user !== undefined &&\n payload.user.toLowerCase() !== input.grantorAddress.toLowerCase()\n ) {\n return { valid: false, error: \"Grant user does not match grantorAddress\" };\n }\n\n return {\n valid: true,\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n grant: input.grant,\n payload,\n fileIds: fileIds.display,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/protocol/grants.ts"],"sourcesContent":["import { verifyTypedData } from \"viem\";\nimport {\n GRANT_REGISTRATION_TYPES,\n grantRegistrationDomain,\n type DataPortabilityGatewayConfig,\n} from \"./eip712\";\n\nexport interface VerifyGrantRegistrationInput {\n gatewayConfig: DataPortabilityGatewayConfig;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n scopes: string[];\n // Decimal-string uint256 is the wire format; bigint/number are accepted\n // for ergonomics. Must be >= 1 (first registration uses 1; each override\n // strictly increases it — see GRANT_REGISTRATION_TYPES).\n grantVersion: bigint | number | string;\n // Unix seconds. 0 = no expiry. Anything > 0 is enforced against nowSeconds.\n expiresAt: bigint | number | string;\n signature: `0x${string}`;\n nowSeconds?: number;\n}\n\nexport type VerifyGrantRegistrationResult =\n | {\n valid: true;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n scopes: string[];\n grantVersion: string;\n expiresAt: string;\n }\n | {\n valid: false;\n error: string;\n };\n\nfunction isHexString(value: unknown): value is `0x${string}` {\n return typeof value === \"string\" && value.startsWith(\"0x\");\n}\n\nexport function isDataPortabilityGatewayConfig(\n value: unknown,\n): value is DataPortabilityGatewayConfig {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n const config = value as Record<string, unknown>;\n const contracts = config[\"contracts\"];\n if (\n typeof config[\"chainId\"] !== \"number\" ||\n !Number.isInteger(config[\"chainId\"]) ||\n config[\"chainId\"] <= 0 ||\n contracts === null ||\n typeof contracts !== \"object\" ||\n Array.isArray(contracts)\n ) {\n return false;\n }\n const c = contracts as Record<string, unknown>;\n return (\n isHexString(c[\"dataRegistry\"]) &&\n isHexString(c[\"dataPortabilityPermissions\"]) &&\n isHexString(c[\"dataPortabilityServer\"]) &&\n isHexString(c[\"dataPortabilityGrantees\"]) &&\n isHexString(c[\"dataPortabilityEscrow\"])\n );\n}\n\nfunction toUint256(value: bigint | number | string): bigint | null {\n try {\n const big = typeof value === \"bigint\" ? value : BigInt(value);\n if (big < 0n) return null;\n return big;\n } catch {\n return null;\n }\n}\n\nexport async function verifyGrantRegistration(\n input: VerifyGrantRegistrationInput,\n): Promise<VerifyGrantRegistrationResult> {\n if (!Array.isArray(input.scopes) || input.scopes.length === 0) {\n return { valid: false, error: \"scopes must be a non-empty array\" };\n }\n if (!input.scopes.every((scope) => typeof scope === \"string\")) {\n return { valid: false, error: \"scopes must contain only strings\" };\n }\n\n const grantVersion = toUint256(input.grantVersion);\n if (grantVersion === null || grantVersion < 1n) {\n return { valid: false, error: \"grantVersion must be a uint256 >= 1\" };\n }\n\n const expiresAt = toUint256(input.expiresAt);\n if (expiresAt === null) {\n return { valid: false, error: \"expiresAt must be a non-negative uint256\" };\n }\n\n let valid: boolean;\n try {\n valid = await verifyTypedData({\n address: input.grantorAddress,\n domain: grantRegistrationDomain(input.gatewayConfig),\n types: GRANT_REGISTRATION_TYPES,\n primaryType: \"GrantRegistration\",\n message: {\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n scopes: input.scopes,\n grantVersion,\n expiresAt,\n },\n signature: input.signature,\n });\n } catch {\n return { valid: false, error: \"EIP-712 signature verification failed\" };\n }\n\n if (!valid) {\n return { valid: false, error: \"Grant signature does not match grantor\" };\n }\n\n // 0 is the \"no expiry\" sentinel — only enforce when expiresAt > 0.\n const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n if (expiresAt > 0n && expiresAt < BigInt(nowSeconds)) {\n return { valid: false, error: \"Grant has expired\" };\n }\n\n return {\n valid: true,\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n scopes: input.scopes,\n grantVersion: grantVersion.toString(),\n expiresAt: expiresAt.toString(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAgC;AAChC,oBAIO;AA+BP,SAAS,YAAY,OAAwC;AAC3D,SAAO,OAAO,UAAU,YAAY,MAAM,WAAW,IAAI;AAC3D;AAEO,SAAS,+BACd,OACuC;AACvC,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,QAAM,YAAY,OAAO,WAAW;AACpC,MACE,OAAO,OAAO,SAAS,MAAM,YAC7B,CAAC,OAAO,UAAU,OAAO,SAAS,CAAC,KACnC,OAAO,SAAS,KAAK,KACrB,cAAc,QACd,OAAO,cAAc,YACrB,MAAM,QAAQ,SAAS,GACvB;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,SACE,YAAY,EAAE,cAAc,CAAC,KAC7B,YAAY,EAAE,4BAA4B,CAAC,KAC3C,YAAY,EAAE,uBAAuB,CAAC,KACtC,YAAY,EAAE,yBAAyB,CAAC,KACxC,YAAY,EAAE,uBAAuB,CAAC;AAE1C;AAEA,SAAS,UAAU,OAAgD;AACjE,MAAI;AACF,UAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;AAC5D,QAAI,MAAM,GAAI,QAAO;AACrB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,wBACpB,OACwC;AACxC,MAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,OAAO,WAAW,GAAG;AAC7D,WAAO,EAAE,OAAO,OAAO,OAAO,mCAAmC;AAAA,EACnE;AACA,MAAI,CAAC,MAAM,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AAC7D,WAAO,EAAE,OAAO,OAAO,OAAO,mCAAmC;AAAA,EACnE;AAEA,QAAM,eAAe,UAAU,MAAM,YAAY;AACjD,MAAI,iBAAiB,QAAQ,eAAe,IAAI;AAC9C,WAAO,EAAE,OAAO,OAAO,OAAO,sCAAsC;AAAA,EACtE;AAEA,QAAM,YAAY,UAAU,MAAM,SAAS;AAC3C,MAAI,cAAc,MAAM;AACtB,WAAO,EAAE,OAAO,OAAO,OAAO,2CAA2C;AAAA,EAC3E;AAEA,MAAI;AACJ,MAAI;AACF,YAAQ,UAAM,6BAAgB;AAAA,MAC5B,SAAS,MAAM;AAAA,MACf,YAAQ,uCAAwB,MAAM,aAAa;AAAA,MACnD,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,QACP,gBAAgB,MAAM;AAAA,QACtB,WAAW,MAAM;AAAA,QACjB,QAAQ,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,MACA,WAAW,MAAM;AAAA,IACnB,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,EAAE,OAAO,OAAO,OAAO,wCAAwC;AAAA,EACxE;AAEA,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,OAAO,OAAO,OAAO,yCAAyC;AAAA,EACzE;AAGA,QAAM,aAAa,MAAM,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACnE,MAAI,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG;AACpD,WAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB;AAAA,EACpD;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,gBAAgB,MAAM;AAAA,IACtB,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,cAAc,aAAa,SAAS;AAAA,IACpC,WAAW,UAAU,SAAS;AAAA,EAChC;AACF;","names":[]}
@@ -1,17 +1,11 @@
1
1
  import { type DataPortabilityGatewayConfig } from "./eip712";
2
- export interface DataPortabilityGrantPayload {
3
- user?: `0x${string}`;
4
- builder?: `0x${string}`;
5
- scopes: string[];
6
- expiresAt: number;
7
- nonce?: number;
8
- }
9
2
  export interface VerifyGrantRegistrationInput {
10
3
  gatewayConfig: DataPortabilityGatewayConfig;
11
4
  grantorAddress: `0x${string}`;
12
5
  granteeId: `0x${string}`;
13
- grant: string;
14
- fileIds?: Array<string | number | bigint>;
6
+ scopes: string[];
7
+ grantVersion: bigint | number | string;
8
+ expiresAt: bigint | number | string;
15
9
  signature: `0x${string}`;
16
10
  nowSeconds?: number;
17
11
  }
@@ -19,13 +13,12 @@ export type VerifyGrantRegistrationResult = {
19
13
  valid: true;
20
14
  grantorAddress: `0x${string}`;
21
15
  granteeId: `0x${string}`;
22
- grant: string;
23
- payload: DataPortabilityGrantPayload;
24
- fileIds: string[];
16
+ scopes: string[];
17
+ grantVersion: string;
18
+ expiresAt: string;
25
19
  } | {
26
20
  valid: false;
27
21
  error: string;
28
22
  };
29
23
  export declare function isDataPortabilityGatewayConfig(value: unknown): value is DataPortabilityGatewayConfig;
30
- export declare function parseGrantRegistrationPayload(grant: string): DataPortabilityGrantPayload | null;
31
24
  export declare function verifyGrantRegistration(input: VerifyGrantRegistrationInput): Promise<VerifyGrantRegistrationResult>;
@@ -2,7 +2,7 @@ import { verifyTypedData } from "viem";
2
2
  import {
3
3
  GRANT_REGISTRATION_TYPES,
4
4
  grantRegistrationDomain
5
- } from "./eip712";
5
+ } from "./eip712.js";
6
6
  function isHexString(value) {
7
7
  return typeof value === "string" && value.startsWith("0x");
8
8
  }
@@ -16,67 +16,31 @@ function isDataPortabilityGatewayConfig(value) {
16
16
  return false;
17
17
  }
18
18
  const c = contracts;
19
- return isHexString(c["dataRegistry"]) && isHexString(c["dataPortabilityPermissions"]) && isHexString(c["dataPortabilityServer"]) && isHexString(c["dataPortabilityGrantees"]);
19
+ return isHexString(c["dataRegistry"]) && isHexString(c["dataPortabilityPermissions"]) && isHexString(c["dataPortabilityServer"]) && isHexString(c["dataPortabilityGrantees"]) && isHexString(c["dataPortabilityEscrow"]);
20
20
  }
21
- function parseGrantRegistrationPayload(grant) {
22
- let parsed;
21
+ function toUint256(value) {
23
22
  try {
24
- parsed = JSON.parse(grant);
25
- } catch {
26
- return null;
27
- }
28
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
29
- return null;
30
- }
31
- const value = parsed;
32
- if (!Array.isArray(value["scopes"]) || value["scopes"].length === 0) {
33
- return null;
34
- }
35
- if (!value["scopes"].every((scope) => typeof scope === "string")) {
36
- return null;
37
- }
38
- if (typeof value["expiresAt"] !== "number" || !Number.isFinite(value["expiresAt"])) {
39
- return null;
40
- }
41
- if (value["user"] !== void 0 && !isHexString(value["user"])) {
42
- return null;
43
- }
44
- if (value["builder"] !== void 0 && !isHexString(value["builder"])) {
45
- return null;
46
- }
47
- if (value["nonce"] !== void 0 && (typeof value["nonce"] !== "number" || !Number.isFinite(value["nonce"]))) {
48
- return null;
49
- }
50
- return {
51
- user: value["user"],
52
- builder: value["builder"],
53
- scopes: value["scopes"],
54
- expiresAt: value["expiresAt"],
55
- nonce: value["nonce"]
56
- };
57
- }
58
- function parseFileIds(fileIds) {
59
- try {
60
- const values = (fileIds ?? []).map((fileId) => BigInt(fileId));
61
- return {
62
- values,
63
- display: values.map((fileId) => fileId.toString())
64
- };
23
+ const big = typeof value === "bigint" ? value : BigInt(value);
24
+ if (big < 0n) return null;
25
+ return big;
65
26
  } catch {
66
27
  return null;
67
28
  }
68
29
  }
69
30
  async function verifyGrantRegistration(input) {
70
- const payload = parseGrantRegistrationPayload(input.grant);
71
- if (!payload) {
72
- return {
73
- valid: false,
74
- error: "Grant must be JSON with scopes and expiresAt"
75
- };
31
+ if (!Array.isArray(input.scopes) || input.scopes.length === 0) {
32
+ return { valid: false, error: "scopes must be a non-empty array" };
76
33
  }
77
- const fileIds = parseFileIds(input.fileIds);
78
- if (!fileIds) {
79
- return { valid: false, error: "fileIds must contain integer values" };
34
+ if (!input.scopes.every((scope) => typeof scope === "string")) {
35
+ return { valid: false, error: "scopes must contain only strings" };
36
+ }
37
+ const grantVersion = toUint256(input.grantVersion);
38
+ if (grantVersion === null || grantVersion < 1n) {
39
+ return { valid: false, error: "grantVersion must be a uint256 >= 1" };
40
+ }
41
+ const expiresAt = toUint256(input.expiresAt);
42
+ if (expiresAt === null) {
43
+ return { valid: false, error: "expiresAt must be a non-negative uint256" };
80
44
  }
81
45
  let valid;
82
46
  try {
@@ -88,8 +52,9 @@ async function verifyGrantRegistration(input) {
88
52
  message: {
89
53
  grantorAddress: input.grantorAddress,
90
54
  granteeId: input.granteeId,
91
- grant: input.grant,
92
- fileIds: fileIds.values
55
+ scopes: input.scopes,
56
+ grantVersion,
57
+ expiresAt
93
58
  },
94
59
  signature: input.signature
95
60
  });
@@ -100,24 +65,20 @@ async function verifyGrantRegistration(input) {
100
65
  return { valid: false, error: "Grant signature does not match grantor" };
101
66
  }
102
67
  const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1e3);
103
- if (payload.expiresAt > 0 && payload.expiresAt < nowSeconds) {
68
+ if (expiresAt > 0n && expiresAt < BigInt(nowSeconds)) {
104
69
  return { valid: false, error: "Grant has expired" };
105
70
  }
106
- if (payload.user !== void 0 && payload.user.toLowerCase() !== input.grantorAddress.toLowerCase()) {
107
- return { valid: false, error: "Grant user does not match grantorAddress" };
108
- }
109
71
  return {
110
72
  valid: true,
111
73
  grantorAddress: input.grantorAddress,
112
74
  granteeId: input.granteeId,
113
- grant: input.grant,
114
- payload,
115
- fileIds: fileIds.display
75
+ scopes: input.scopes,
76
+ grantVersion: grantVersion.toString(),
77
+ expiresAt: expiresAt.toString()
116
78
  };
117
79
  }
118
80
  export {
119
81
  isDataPortabilityGatewayConfig,
120
- parseGrantRegistrationPayload,
121
82
  verifyGrantRegistration
122
83
  };
123
84
  //# sourceMappingURL=grants.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/protocol/grants.ts"],"sourcesContent":["import { verifyTypedData } from \"viem\";\nimport {\n GRANT_REGISTRATION_TYPES,\n grantRegistrationDomain,\n type DataPortabilityGatewayConfig,\n} from \"./eip712\";\n\nexport interface DataPortabilityGrantPayload {\n user?: `0x${string}`;\n builder?: `0x${string}`;\n scopes: string[];\n expiresAt: number;\n nonce?: number;\n}\n\nexport interface VerifyGrantRegistrationInput {\n gatewayConfig: DataPortabilityGatewayConfig;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n grant: string;\n fileIds?: Array<string | number | bigint>;\n signature: `0x${string}`;\n nowSeconds?: number;\n}\n\nexport type VerifyGrantRegistrationResult =\n | {\n valid: true;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n grant: string;\n payload: DataPortabilityGrantPayload;\n fileIds: string[];\n }\n | {\n valid: false;\n error: string;\n };\n\nfunction isHexString(value: unknown): value is `0x${string}` {\n return typeof value === \"string\" && value.startsWith(\"0x\");\n}\n\nexport function isDataPortabilityGatewayConfig(\n value: unknown,\n): value is DataPortabilityGatewayConfig {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n const config = value as Record<string, unknown>;\n const contracts = config[\"contracts\"];\n if (\n typeof config[\"chainId\"] !== \"number\" ||\n !Number.isInteger(config[\"chainId\"]) ||\n config[\"chainId\"] <= 0 ||\n contracts === null ||\n typeof contracts !== \"object\" ||\n Array.isArray(contracts)\n ) {\n return false;\n }\n const c = contracts as Record<string, unknown>;\n return (\n isHexString(c[\"dataRegistry\"]) &&\n isHexString(c[\"dataPortabilityPermissions\"]) &&\n isHexString(c[\"dataPortabilityServer\"]) &&\n isHexString(c[\"dataPortabilityGrantees\"])\n );\n}\n\nexport function parseGrantRegistrationPayload(\n grant: string,\n): DataPortabilityGrantPayload | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(grant);\n } catch {\n return null;\n }\n if (parsed === null || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return null;\n }\n const value = parsed as Record<string, unknown>;\n if (!Array.isArray(value[\"scopes\"]) || value[\"scopes\"].length === 0) {\n return null;\n }\n if (!value[\"scopes\"].every((scope) => typeof scope === \"string\")) {\n return null;\n }\n if (\n typeof value[\"expiresAt\"] !== \"number\" ||\n !Number.isFinite(value[\"expiresAt\"])\n ) {\n return null;\n }\n if (value[\"user\"] !== undefined && !isHexString(value[\"user\"])) {\n return null;\n }\n if (value[\"builder\"] !== undefined && !isHexString(value[\"builder\"])) {\n return null;\n }\n if (\n value[\"nonce\"] !== undefined &&\n (typeof value[\"nonce\"] !== \"number\" || !Number.isFinite(value[\"nonce\"]))\n ) {\n return null;\n }\n return {\n user: value[\"user\"] as `0x${string}` | undefined,\n builder: value[\"builder\"] as `0x${string}` | undefined,\n scopes: value[\"scopes\"] as string[],\n expiresAt: value[\"expiresAt\"],\n nonce: value[\"nonce\"] as number | undefined,\n };\n}\n\nfunction parseFileIds(fileIds: Array<string | number | bigint> | undefined): {\n values: bigint[];\n display: string[];\n} | null {\n try {\n const values = (fileIds ?? []).map((fileId) => BigInt(fileId));\n return {\n values,\n display: values.map((fileId) => fileId.toString()),\n };\n } catch {\n return null;\n }\n}\n\nexport async function verifyGrantRegistration(\n input: VerifyGrantRegistrationInput,\n): Promise<VerifyGrantRegistrationResult> {\n const payload = parseGrantRegistrationPayload(input.grant);\n if (!payload) {\n return {\n valid: false,\n error: \"Grant must be JSON with scopes and expiresAt\",\n };\n }\n\n const fileIds = parseFileIds(input.fileIds);\n if (!fileIds) {\n return { valid: false, error: \"fileIds must contain integer values\" };\n }\n\n let valid: boolean;\n try {\n valid = await verifyTypedData({\n address: input.grantorAddress,\n domain: grantRegistrationDomain(input.gatewayConfig),\n types: GRANT_REGISTRATION_TYPES,\n primaryType: \"GrantRegistration\",\n message: {\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n grant: input.grant,\n fileIds: fileIds.values,\n },\n signature: input.signature,\n });\n } catch {\n return { valid: false, error: \"EIP-712 signature verification failed\" };\n }\n\n if (!valid) {\n return { valid: false, error: \"Grant signature does not match grantor\" };\n }\n\n const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n if (payload.expiresAt > 0 && payload.expiresAt < nowSeconds) {\n return { valid: false, error: \"Grant has expired\" };\n }\n\n if (\n payload.user !== undefined &&\n payload.user.toLowerCase() !== input.grantorAddress.toLowerCase()\n ) {\n return { valid: false, error: \"Grant user does not match grantorAddress\" };\n }\n\n return {\n valid: true,\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n grant: input.grant,\n payload,\n fileIds: fileIds.display,\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/protocol/grants.ts"],"sourcesContent":["import { verifyTypedData } from \"viem\";\nimport {\n GRANT_REGISTRATION_TYPES,\n grantRegistrationDomain,\n type DataPortabilityGatewayConfig,\n} from \"./eip712\";\n\nexport interface VerifyGrantRegistrationInput {\n gatewayConfig: DataPortabilityGatewayConfig;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n scopes: string[];\n // Decimal-string uint256 is the wire format; bigint/number are accepted\n // for ergonomics. Must be >= 1 (first registration uses 1; each override\n // strictly increases it — see GRANT_REGISTRATION_TYPES).\n grantVersion: bigint | number | string;\n // Unix seconds. 0 = no expiry. Anything > 0 is enforced against nowSeconds.\n expiresAt: bigint | number | string;\n signature: `0x${string}`;\n nowSeconds?: number;\n}\n\nexport type VerifyGrantRegistrationResult =\n | {\n valid: true;\n grantorAddress: `0x${string}`;\n granteeId: `0x${string}`;\n scopes: string[];\n grantVersion: string;\n expiresAt: string;\n }\n | {\n valid: false;\n error: string;\n };\n\nfunction isHexString(value: unknown): value is `0x${string}` {\n return typeof value === \"string\" && value.startsWith(\"0x\");\n}\n\nexport function isDataPortabilityGatewayConfig(\n value: unknown,\n): value is DataPortabilityGatewayConfig {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n const config = value as Record<string, unknown>;\n const contracts = config[\"contracts\"];\n if (\n typeof config[\"chainId\"] !== \"number\" ||\n !Number.isInteger(config[\"chainId\"]) ||\n config[\"chainId\"] <= 0 ||\n contracts === null ||\n typeof contracts !== \"object\" ||\n Array.isArray(contracts)\n ) {\n return false;\n }\n const c = contracts as Record<string, unknown>;\n return (\n isHexString(c[\"dataRegistry\"]) &&\n isHexString(c[\"dataPortabilityPermissions\"]) &&\n isHexString(c[\"dataPortabilityServer\"]) &&\n isHexString(c[\"dataPortabilityGrantees\"]) &&\n isHexString(c[\"dataPortabilityEscrow\"])\n );\n}\n\nfunction toUint256(value: bigint | number | string): bigint | null {\n try {\n const big = typeof value === \"bigint\" ? value : BigInt(value);\n if (big < 0n) return null;\n return big;\n } catch {\n return null;\n }\n}\n\nexport async function verifyGrantRegistration(\n input: VerifyGrantRegistrationInput,\n): Promise<VerifyGrantRegistrationResult> {\n if (!Array.isArray(input.scopes) || input.scopes.length === 0) {\n return { valid: false, error: \"scopes must be a non-empty array\" };\n }\n if (!input.scopes.every((scope) => typeof scope === \"string\")) {\n return { valid: false, error: \"scopes must contain only strings\" };\n }\n\n const grantVersion = toUint256(input.grantVersion);\n if (grantVersion === null || grantVersion < 1n) {\n return { valid: false, error: \"grantVersion must be a uint256 >= 1\" };\n }\n\n const expiresAt = toUint256(input.expiresAt);\n if (expiresAt === null) {\n return { valid: false, error: \"expiresAt must be a non-negative uint256\" };\n }\n\n let valid: boolean;\n try {\n valid = await verifyTypedData({\n address: input.grantorAddress,\n domain: grantRegistrationDomain(input.gatewayConfig),\n types: GRANT_REGISTRATION_TYPES,\n primaryType: \"GrantRegistration\",\n message: {\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n scopes: input.scopes,\n grantVersion,\n expiresAt,\n },\n signature: input.signature,\n });\n } catch {\n return { valid: false, error: \"EIP-712 signature verification failed\" };\n }\n\n if (!valid) {\n return { valid: false, error: \"Grant signature does not match grantor\" };\n }\n\n // 0 is the \"no expiry\" sentinel — only enforce when expiresAt > 0.\n const nowSeconds = input.nowSeconds ?? Math.floor(Date.now() / 1000);\n if (expiresAt > 0n && expiresAt < BigInt(nowSeconds)) {\n return { valid: false, error: \"Grant has expired\" };\n }\n\n return {\n valid: true,\n grantorAddress: input.grantorAddress,\n granteeId: input.granteeId,\n scopes: input.scopes,\n grantVersion: grantVersion.toString(),\n expiresAt: expiresAt.toString(),\n };\n}\n"],"mappings":"AAAA,SAAS,uBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AA+BP,SAAS,YAAY,OAAwC;AAC3D,SAAO,OAAO,UAAU,YAAY,MAAM,WAAW,IAAI;AAC3D;AAEO,SAAS,+BACd,OACuC;AACvC,MAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AACvE,WAAO;AAAA,EACT;AACA,QAAM,SAAS;AACf,QAAM,YAAY,OAAO,WAAW;AACpC,MACE,OAAO,OAAO,SAAS,MAAM,YAC7B,CAAC,OAAO,UAAU,OAAO,SAAS,CAAC,KACnC,OAAO,SAAS,KAAK,KACrB,cAAc,QACd,OAAO,cAAc,YACrB,MAAM,QAAQ,SAAS,GACvB;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AACV,SACE,YAAY,EAAE,cAAc,CAAC,KAC7B,YAAY,EAAE,4BAA4B,CAAC,KAC3C,YAAY,EAAE,uBAAuB,CAAC,KACtC,YAAY,EAAE,yBAAyB,CAAC,KACxC,YAAY,EAAE,uBAAuB,CAAC;AAE1C;AAEA,SAAS,UAAU,OAAgD;AACjE,MAAI;AACF,UAAM,MAAM,OAAO,UAAU,WAAW,QAAQ,OAAO,KAAK;AAC5D,QAAI,MAAM,GAAI,QAAO;AACrB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,wBACpB,OACwC;AACxC,MAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,MAAM,OAAO,WAAW,GAAG;AAC7D,WAAO,EAAE,OAAO,OAAO,OAAO,mCAAmC;AAAA,EACnE;AACA,MAAI,CAAC,MAAM,OAAO,MAAM,CAAC,UAAU,OAAO,UAAU,QAAQ,GAAG;AAC7D,WAAO,EAAE,OAAO,OAAO,OAAO,mCAAmC;AAAA,EACnE;AAEA,QAAM,eAAe,UAAU,MAAM,YAAY;AACjD,MAAI,iBAAiB,QAAQ,eAAe,IAAI;AAC9C,WAAO,EAAE,OAAO,OAAO,OAAO,sCAAsC;AAAA,EACtE;AAEA,QAAM,YAAY,UAAU,MAAM,SAAS;AAC3C,MAAI,cAAc,MAAM;AACtB,WAAO,EAAE,OAAO,OAAO,OAAO,2CAA2C;AAAA,EAC3E;AAEA,MAAI;AACJ,MAAI;AACF,YAAQ,MAAM,gBAAgB;AAAA,MAC5B,SAAS,MAAM;AAAA,MACf,QAAQ,wBAAwB,MAAM,aAAa;AAAA,MACnD,OAAO;AAAA,MACP,aAAa;AAAA,MACb,SAAS;AAAA,QACP,gBAAgB,MAAM;AAAA,QACtB,WAAW,MAAM;AAAA,QACjB,QAAQ,MAAM;AAAA,QACd;AAAA,QACA;AAAA,MACF;AAAA,MACA,WAAW,MAAM;AAAA,IACnB,CAAC;AAAA,EACH,QAAQ;AACN,WAAO,EAAE,OAAO,OAAO,OAAO,wCAAwC;AAAA,EACxE;AAEA,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,OAAO,OAAO,OAAO,yCAAyC;AAAA,EACzE;AAGA,QAAM,aAAa,MAAM,cAAc,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AACnE,MAAI,YAAY,MAAM,YAAY,OAAO,UAAU,GAAG;AACpD,WAAO,EAAE,OAAO,OAAO,OAAO,oBAAoB;AAAA,EACpD;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,IACP,gBAAgB,MAAM;AAAA,IACtB,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,cAAc,aAAa,SAAS;AAAA,IACpC,WAAW,UAAU,SAAS;AAAA,EAChC;AACF;","names":[]}
@@ -0,0 +1,93 @@
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 personal_server_lite_owner_binding_exports = {};
20
+ __export(personal_server_lite_owner_binding_exports, {
21
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX: () => PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX,
22
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE: () => PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,
23
+ PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION: () => PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION,
24
+ buildPersonalServerLiteOwnerBindingMessage: () => buildPersonalServerLiteOwnerBindingMessage,
25
+ buildPersonalServerLiteOwnerBindingSignature: () => buildPersonalServerLiteOwnerBindingSignature,
26
+ createViemPersonalServerLiteOwnerBindingSigner: () => createViemPersonalServerLiteOwnerBindingSigner,
27
+ signPersonalServerLiteOwnerBinding: () => signPersonalServerLiteOwnerBinding
28
+ });
29
+ module.exports = __toCommonJS(personal_server_lite_owner_binding_exports);
30
+ var import_viem = require("viem");
31
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION = "vana.account.v1";
32
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE = "ps-lite-owner";
33
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX = `${PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION}:${PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE}:`;
34
+ function assertAddress(value, name) {
35
+ if (!(0, import_viem.isAddress)(value)) {
36
+ throw new Error(`${name} must be a valid EVM address`);
37
+ }
38
+ }
39
+ function getAccountAddress(account) {
40
+ if (!account) {
41
+ return void 0;
42
+ }
43
+ return typeof account === "string" ? account : account.address;
44
+ }
45
+ function isPersonalServerLiteOwnerBindingSigner(source) {
46
+ return "address" in source && typeof source.signMessage === "function";
47
+ }
48
+ function buildPersonalServerLiteOwnerBindingMessage(ownerAddress) {
49
+ assertAddress(ownerAddress, "ownerAddress");
50
+ return `${PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${ownerAddress.toLowerCase()}`;
51
+ }
52
+ function createViemPersonalServerLiteOwnerBindingSigner(source, options = {}) {
53
+ if (isPersonalServerLiteOwnerBindingSigner(source)) {
54
+ return source;
55
+ }
56
+ const accountAddress = getAccountAddress(options.account) ?? getAccountAddress(source.account);
57
+ if (accountAddress) {
58
+ return {
59
+ address: accountAddress,
60
+ signMessage: ({ message }) => source.signMessage({
61
+ account: options.account ?? source.account ?? accountAddress,
62
+ message
63
+ })
64
+ };
65
+ }
66
+ throw new Error(
67
+ "Viem wallet client requires an account option or account property"
68
+ );
69
+ }
70
+ async function buildPersonalServerLiteOwnerBindingSignature(input) {
71
+ const message = buildPersonalServerLiteOwnerBindingMessage(
72
+ input.signer.address
73
+ );
74
+ const signature = await input.signer.signMessage({ message });
75
+ return {
76
+ signature,
77
+ signerAddress: input.signer.address,
78
+ message,
79
+ purpose: PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE
80
+ };
81
+ }
82
+ const signPersonalServerLiteOwnerBinding = buildPersonalServerLiteOwnerBindingSignature;
83
+ // Annotate the CommonJS export names for ESM import in node:
84
+ 0 && (module.exports = {
85
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX,
86
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,
87
+ PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION,
88
+ buildPersonalServerLiteOwnerBindingMessage,
89
+ buildPersonalServerLiteOwnerBindingSignature,
90
+ createViemPersonalServerLiteOwnerBindingSigner,
91
+ signPersonalServerLiteOwnerBinding
92
+ });
93
+ //# sourceMappingURL=personal-server-lite-owner-binding.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/protocol/personal-server-lite-owner-binding.ts"],"sourcesContent":["/**\n * PS Lite owner-binding message and signing helpers.\n *\n * PS Lite uses this replayable personal-sign message as a wallet-owned input\n * for opening the user's local encrypted runtime. This is intentionally\n * separate from Personal Server registration, which is EIP-712 typed data.\n *\n * @category Protocol\n */\n\nimport {\n isAddress,\n type Account,\n type Address,\n type Hex,\n type SignableMessage,\n} from \"viem\";\n\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION = \"vana.account.v1\";\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE = \"ps-lite-owner\";\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX =\n `${PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION}:${PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE}:` as const;\n\nexport type PersonalServerLiteOwnerBindingPurpose =\n typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE;\n\nexport type PersonalServerLiteOwnerBindingMessage =\n `${typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${Lowercase<Address>}`;\n\nexport interface PersonalServerLiteOwnerBindingSigner {\n address: Address;\n signMessage(input: {\n message: PersonalServerLiteOwnerBindingMessage;\n }): Promise<Hex> | Hex;\n}\n\nexport interface ViemPersonalServerLiteOwnerBindingWalletClient {\n account?: Account | Address | null;\n signMessage(input: {\n account?: Account | Address;\n message: SignableMessage;\n }): Promise<Hex>;\n}\n\nexport type ViemPersonalServerLiteOwnerBindingSignerSource =\n | PersonalServerLiteOwnerBindingSigner\n | ViemPersonalServerLiteOwnerBindingWalletClient;\n\nexport interface BuildPersonalServerLiteOwnerBindingSignatureInput {\n signer: PersonalServerLiteOwnerBindingSigner;\n}\n\nexport interface PersonalServerLiteOwnerBindingSignature {\n signature: Hex;\n signerAddress: Address;\n message: PersonalServerLiteOwnerBindingMessage;\n purpose: PersonalServerLiteOwnerBindingPurpose;\n}\n\nfunction assertAddress(value: Address, name: string): void {\n if (!isAddress(value)) {\n throw new Error(`${name} must be a valid EVM address`);\n }\n}\n\nfunction getAccountAddress(\n account: Account | Address | null | undefined,\n): Address | undefined {\n if (!account) {\n return undefined;\n }\n\n return typeof account === \"string\" ? account : account.address;\n}\n\nfunction isPersonalServerLiteOwnerBindingSigner(\n source: ViemPersonalServerLiteOwnerBindingSignerSource,\n): source is PersonalServerLiteOwnerBindingSigner {\n return \"address\" in source && typeof source.signMessage === \"function\";\n}\n\nexport function buildPersonalServerLiteOwnerBindingMessage(\n ownerAddress: Address,\n): PersonalServerLiteOwnerBindingMessage {\n assertAddress(ownerAddress, \"ownerAddress\");\n return `${PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${ownerAddress.toLowerCase()}` as PersonalServerLiteOwnerBindingMessage;\n}\n\nexport function createViemPersonalServerLiteOwnerBindingSigner(\n source: ViemPersonalServerLiteOwnerBindingSignerSource,\n options: { account?: Account | Address } = {},\n): PersonalServerLiteOwnerBindingSigner {\n if (isPersonalServerLiteOwnerBindingSigner(source)) {\n return source;\n }\n\n const accountAddress =\n getAccountAddress(options.account) ?? getAccountAddress(source.account);\n\n if (accountAddress) {\n return {\n address: accountAddress,\n signMessage: ({ message }) =>\n source.signMessage({\n account: options.account ?? source.account ?? accountAddress,\n message,\n }),\n };\n }\n\n throw new Error(\n \"Viem wallet client requires an account option or account property\",\n );\n}\n\nexport async function buildPersonalServerLiteOwnerBindingSignature(\n input: BuildPersonalServerLiteOwnerBindingSignatureInput,\n): Promise<PersonalServerLiteOwnerBindingSignature> {\n const message = buildPersonalServerLiteOwnerBindingMessage(\n input.signer.address,\n );\n const signature = await input.signer.signMessage({ message });\n\n return {\n signature,\n signerAddress: input.signer.address,\n message,\n purpose: PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,\n };\n}\n\nexport const signPersonalServerLiteOwnerBinding =\n buildPersonalServerLiteOwnerBindingSignature;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,kBAMO;AAEA,MAAM,6CAA6C;AACnD,MAAM,6CAA6C;AACnD,MAAM,4CACX,GAAG,0CAA0C,IAAI,0CAA0C;AAsC7F,SAAS,cAAc,OAAgB,MAAoB;AACzD,MAAI,KAAC,uBAAU,KAAK,GAAG;AACrB,UAAM,IAAI,MAAM,GAAG,IAAI,8BAA8B;AAAA,EACvD;AACF;AAEA,SAAS,kBACP,SACqB;AACrB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;AACzD;AAEA,SAAS,uCACP,QACgD;AAChD,SAAO,aAAa,UAAU,OAAO,OAAO,gBAAgB;AAC9D;AAEO,SAAS,2CACd,cACuC;AACvC,gBAAc,cAAc,cAAc;AAC1C,SAAO,GAAG,yCAAyC,GAAG,aAAa,YAAY,CAAC;AAClF;AAEO,SAAS,+CACd,QACA,UAA2C,CAAC,GACN;AACtC,MAAI,uCAAuC,MAAM,GAAG;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,iBACJ,kBAAkB,QAAQ,OAAO,KAAK,kBAAkB,OAAO,OAAO;AAExE,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,CAAC,EAAE,QAAQ,MACtB,OAAO,YAAY;AAAA,QACjB,SAAS,QAAQ,WAAW,OAAO,WAAW;AAAA,QAC9C;AAAA,MACF,CAAC;AAAA,IACL;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAsB,6CACpB,OACkD;AAClD,QAAM,UAAU;AAAA,IACd,MAAM,OAAO;AAAA,EACf;AACA,QAAM,YAAY,MAAM,MAAM,OAAO,YAAY,EAAE,QAAQ,CAAC;AAE5D,SAAO;AAAA,IACL;AAAA,IACA,eAAe,MAAM,OAAO;AAAA,IAC5B;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAEO,MAAM,qCACX;","names":[]}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * PS Lite owner-binding message and signing helpers.
3
+ *
4
+ * PS Lite uses this replayable personal-sign message as a wallet-owned input
5
+ * for opening the user's local encrypted runtime. This is intentionally
6
+ * separate from Personal Server registration, which is EIP-712 typed data.
7
+ *
8
+ * @category Protocol
9
+ */
10
+ import { type Account, type Address, type Hex, type SignableMessage } from "viem";
11
+ export declare const PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION = "vana.account.v1";
12
+ export declare const PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE = "ps-lite-owner";
13
+ export declare const PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX: "vana.account.v1:ps-lite-owner:";
14
+ export type PersonalServerLiteOwnerBindingPurpose = typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE;
15
+ export type PersonalServerLiteOwnerBindingMessage = `${typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${Lowercase<Address>}`;
16
+ export interface PersonalServerLiteOwnerBindingSigner {
17
+ address: Address;
18
+ signMessage(input: {
19
+ message: PersonalServerLiteOwnerBindingMessage;
20
+ }): Promise<Hex> | Hex;
21
+ }
22
+ export interface ViemPersonalServerLiteOwnerBindingWalletClient {
23
+ account?: Account | Address | null;
24
+ signMessage(input: {
25
+ account?: Account | Address;
26
+ message: SignableMessage;
27
+ }): Promise<Hex>;
28
+ }
29
+ export type ViemPersonalServerLiteOwnerBindingSignerSource = PersonalServerLiteOwnerBindingSigner | ViemPersonalServerLiteOwnerBindingWalletClient;
30
+ export interface BuildPersonalServerLiteOwnerBindingSignatureInput {
31
+ signer: PersonalServerLiteOwnerBindingSigner;
32
+ }
33
+ export interface PersonalServerLiteOwnerBindingSignature {
34
+ signature: Hex;
35
+ signerAddress: Address;
36
+ message: PersonalServerLiteOwnerBindingMessage;
37
+ purpose: PersonalServerLiteOwnerBindingPurpose;
38
+ }
39
+ export declare function buildPersonalServerLiteOwnerBindingMessage(ownerAddress: Address): PersonalServerLiteOwnerBindingMessage;
40
+ export declare function createViemPersonalServerLiteOwnerBindingSigner(source: ViemPersonalServerLiteOwnerBindingSignerSource, options?: {
41
+ account?: Account | Address;
42
+ }): PersonalServerLiteOwnerBindingSigner;
43
+ export declare function buildPersonalServerLiteOwnerBindingSignature(input: BuildPersonalServerLiteOwnerBindingSignatureInput): Promise<PersonalServerLiteOwnerBindingSignature>;
44
+ export declare const signPersonalServerLiteOwnerBinding: typeof buildPersonalServerLiteOwnerBindingSignature;
@@ -0,0 +1,65 @@
1
+ import {
2
+ isAddress
3
+ } from "viem";
4
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION = "vana.account.v1";
5
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE = "ps-lite-owner";
6
+ const PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX = `${PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION}:${PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE}:`;
7
+ function assertAddress(value, name) {
8
+ if (!isAddress(value)) {
9
+ throw new Error(`${name} must be a valid EVM address`);
10
+ }
11
+ }
12
+ function getAccountAddress(account) {
13
+ if (!account) {
14
+ return void 0;
15
+ }
16
+ return typeof account === "string" ? account : account.address;
17
+ }
18
+ function isPersonalServerLiteOwnerBindingSigner(source) {
19
+ return "address" in source && typeof source.signMessage === "function";
20
+ }
21
+ function buildPersonalServerLiteOwnerBindingMessage(ownerAddress) {
22
+ assertAddress(ownerAddress, "ownerAddress");
23
+ return `${PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${ownerAddress.toLowerCase()}`;
24
+ }
25
+ function createViemPersonalServerLiteOwnerBindingSigner(source, options = {}) {
26
+ if (isPersonalServerLiteOwnerBindingSigner(source)) {
27
+ return source;
28
+ }
29
+ const accountAddress = getAccountAddress(options.account) ?? getAccountAddress(source.account);
30
+ if (accountAddress) {
31
+ return {
32
+ address: accountAddress,
33
+ signMessage: ({ message }) => source.signMessage({
34
+ account: options.account ?? source.account ?? accountAddress,
35
+ message
36
+ })
37
+ };
38
+ }
39
+ throw new Error(
40
+ "Viem wallet client requires an account option or account property"
41
+ );
42
+ }
43
+ async function buildPersonalServerLiteOwnerBindingSignature(input) {
44
+ const message = buildPersonalServerLiteOwnerBindingMessage(
45
+ input.signer.address
46
+ );
47
+ const signature = await input.signer.signMessage({ message });
48
+ return {
49
+ signature,
50
+ signerAddress: input.signer.address,
51
+ message,
52
+ purpose: PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE
53
+ };
54
+ }
55
+ const signPersonalServerLiteOwnerBinding = buildPersonalServerLiteOwnerBindingSignature;
56
+ export {
57
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX,
58
+ PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,
59
+ PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION,
60
+ buildPersonalServerLiteOwnerBindingMessage,
61
+ buildPersonalServerLiteOwnerBindingSignature,
62
+ createViemPersonalServerLiteOwnerBindingSigner,
63
+ signPersonalServerLiteOwnerBinding
64
+ };
65
+ //# sourceMappingURL=personal-server-lite-owner-binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/protocol/personal-server-lite-owner-binding.ts"],"sourcesContent":["/**\n * PS Lite owner-binding message and signing helpers.\n *\n * PS Lite uses this replayable personal-sign message as a wallet-owned input\n * for opening the user's local encrypted runtime. This is intentionally\n * separate from Personal Server registration, which is EIP-712 typed data.\n *\n * @category Protocol\n */\n\nimport {\n isAddress,\n type Account,\n type Address,\n type Hex,\n type SignableMessage,\n} from \"viem\";\n\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION = \"vana.account.v1\";\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE = \"ps-lite-owner\";\nexport const PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX =\n `${PERSONAL_SERVER_LITE_OWNER_BINDING_VERSION}:${PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE}:` as const;\n\nexport type PersonalServerLiteOwnerBindingPurpose =\n typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE;\n\nexport type PersonalServerLiteOwnerBindingMessage =\n `${typeof PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${Lowercase<Address>}`;\n\nexport interface PersonalServerLiteOwnerBindingSigner {\n address: Address;\n signMessage(input: {\n message: PersonalServerLiteOwnerBindingMessage;\n }): Promise<Hex> | Hex;\n}\n\nexport interface ViemPersonalServerLiteOwnerBindingWalletClient {\n account?: Account | Address | null;\n signMessage(input: {\n account?: Account | Address;\n message: SignableMessage;\n }): Promise<Hex>;\n}\n\nexport type ViemPersonalServerLiteOwnerBindingSignerSource =\n | PersonalServerLiteOwnerBindingSigner\n | ViemPersonalServerLiteOwnerBindingWalletClient;\n\nexport interface BuildPersonalServerLiteOwnerBindingSignatureInput {\n signer: PersonalServerLiteOwnerBindingSigner;\n}\n\nexport interface PersonalServerLiteOwnerBindingSignature {\n signature: Hex;\n signerAddress: Address;\n message: PersonalServerLiteOwnerBindingMessage;\n purpose: PersonalServerLiteOwnerBindingPurpose;\n}\n\nfunction assertAddress(value: Address, name: string): void {\n if (!isAddress(value)) {\n throw new Error(`${name} must be a valid EVM address`);\n }\n}\n\nfunction getAccountAddress(\n account: Account | Address | null | undefined,\n): Address | undefined {\n if (!account) {\n return undefined;\n }\n\n return typeof account === \"string\" ? account : account.address;\n}\n\nfunction isPersonalServerLiteOwnerBindingSigner(\n source: ViemPersonalServerLiteOwnerBindingSignerSource,\n): source is PersonalServerLiteOwnerBindingSigner {\n return \"address\" in source && typeof source.signMessage === \"function\";\n}\n\nexport function buildPersonalServerLiteOwnerBindingMessage(\n ownerAddress: Address,\n): PersonalServerLiteOwnerBindingMessage {\n assertAddress(ownerAddress, \"ownerAddress\");\n return `${PERSONAL_SERVER_LITE_OWNER_BINDING_PREFIX}${ownerAddress.toLowerCase()}` as PersonalServerLiteOwnerBindingMessage;\n}\n\nexport function createViemPersonalServerLiteOwnerBindingSigner(\n source: ViemPersonalServerLiteOwnerBindingSignerSource,\n options: { account?: Account | Address } = {},\n): PersonalServerLiteOwnerBindingSigner {\n if (isPersonalServerLiteOwnerBindingSigner(source)) {\n return source;\n }\n\n const accountAddress =\n getAccountAddress(options.account) ?? getAccountAddress(source.account);\n\n if (accountAddress) {\n return {\n address: accountAddress,\n signMessage: ({ message }) =>\n source.signMessage({\n account: options.account ?? source.account ?? accountAddress,\n message,\n }),\n };\n }\n\n throw new Error(\n \"Viem wallet client requires an account option or account property\",\n );\n}\n\nexport async function buildPersonalServerLiteOwnerBindingSignature(\n input: BuildPersonalServerLiteOwnerBindingSignatureInput,\n): Promise<PersonalServerLiteOwnerBindingSignature> {\n const message = buildPersonalServerLiteOwnerBindingMessage(\n input.signer.address,\n );\n const signature = await input.signer.signMessage({ message });\n\n return {\n signature,\n signerAddress: input.signer.address,\n message,\n purpose: PERSONAL_SERVER_LITE_OWNER_BINDING_PURPOSE,\n };\n}\n\nexport const signPersonalServerLiteOwnerBinding =\n buildPersonalServerLiteOwnerBindingSignature;\n"],"mappings":"AAUA;AAAA,EACE;AAAA,OAKK;AAEA,MAAM,6CAA6C;AACnD,MAAM,6CAA6C;AACnD,MAAM,4CACX,GAAG,0CAA0C,IAAI,0CAA0C;AAsC7F,SAAS,cAAc,OAAgB,MAAoB;AACzD,MAAI,CAAC,UAAU,KAAK,GAAG;AACrB,UAAM,IAAI,MAAM,GAAG,IAAI,8BAA8B;AAAA,EACvD;AACF;AAEA,SAAS,kBACP,SACqB;AACrB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;AACzD;AAEA,SAAS,uCACP,QACgD;AAChD,SAAO,aAAa,UAAU,OAAO,OAAO,gBAAgB;AAC9D;AAEO,SAAS,2CACd,cACuC;AACvC,gBAAc,cAAc,cAAc;AAC1C,SAAO,GAAG,yCAAyC,GAAG,aAAa,YAAY,CAAC;AAClF;AAEO,SAAS,+CACd,QACA,UAA2C,CAAC,GACN;AACtC,MAAI,uCAAuC,MAAM,GAAG;AAClD,WAAO;AAAA,EACT;AAEA,QAAM,iBACJ,kBAAkB,QAAQ,OAAO,KAAK,kBAAkB,OAAO,OAAO;AAExE,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,aAAa,CAAC,EAAE,QAAQ,MACtB,OAAO,YAAY;AAAA,QACjB,SAAS,QAAQ,WAAW,OAAO,WAAW;AAAA,QAC9C;AAAA,MACF,CAAC;AAAA,IACL;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEA,eAAsB,6CACpB,OACkD;AAClD,QAAM,UAAU;AAAA,IACd,MAAM,OAAO;AAAA,EACf;AACA,QAAM,YAAY,MAAM,MAAM,OAAO,YAAY,EAAE,QAAQ,CAAC;AAE5D,SAAO;AAAA,IACL;AAAA,IACA,eAAe,MAAM,OAAO;AAAA,IAC5B;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAEO,MAAM,qCACX;","names":[]}
@@ -0,0 +1,122 @@
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 personal_server_registration_exports = {};
20
+ __export(personal_server_registration_exports, {
21
+ PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID: () => PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID,
22
+ PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT: () => PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT,
23
+ buildPersonalServerRegistrationSignature: () => buildPersonalServerRegistrationSignature,
24
+ buildPersonalServerRegistrationTypedData: () => buildPersonalServerRegistrationTypedData,
25
+ createViemPersonalServerRegistrationSigner: () => createViemPersonalServerRegistrationSigner,
26
+ personalServerRegistrationDomain: () => personalServerRegistrationDomain,
27
+ registerPersonalServerSignature: () => registerPersonalServerSignature
28
+ });
29
+ module.exports = __toCommonJS(personal_server_registration_exports);
30
+ var import_viem = require("viem");
31
+ var import_eip712 = require("./eip712");
32
+ const PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID = 1480;
33
+ const PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT = "0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c";
34
+ function assertAddress(value, name) {
35
+ if (!(0, import_viem.isAddress)(value)) {
36
+ throw new Error(`${name} must be a valid EVM address`);
37
+ }
38
+ }
39
+ function getAccountAddress(account) {
40
+ if (!account) {
41
+ return void 0;
42
+ }
43
+ return typeof account === "string" ? account : account.address;
44
+ }
45
+ function isPersonalServerRegistrationSigner(source) {
46
+ return "address" in source && typeof source.signTypedData === "function";
47
+ }
48
+ function createViemPersonalServerRegistrationSigner(source, options = {}) {
49
+ if (isPersonalServerRegistrationSigner(source)) {
50
+ return source;
51
+ }
52
+ const accountAddress = getAccountAddress(options.account) ?? getAccountAddress(source.account);
53
+ if (accountAddress) {
54
+ return {
55
+ address: accountAddress,
56
+ signTypedData: (typedData) => source.signTypedData({
57
+ ...typedData,
58
+ account: options.account ?? source.account ?? accountAddress
59
+ })
60
+ };
61
+ }
62
+ throw new Error(
63
+ "Viem wallet client requires an account option or account property"
64
+ );
65
+ }
66
+ function personalServerRegistrationDomain(input = {}) {
67
+ if (input.config) {
68
+ return (0, import_eip712.serverRegistrationDomain)(input.config);
69
+ }
70
+ const verifyingContract = input.verifyingContract ?? PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT;
71
+ assertAddress(verifyingContract, "verifyingContract");
72
+ return {
73
+ name: "Vana Data Portability",
74
+ version: "1",
75
+ chainId: input.chainId ?? PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID,
76
+ verifyingContract
77
+ };
78
+ }
79
+ function buildPersonalServerRegistrationTypedData(input) {
80
+ assertAddress(input.ownerAddress, "ownerAddress");
81
+ assertAddress(input.serverAddress, "serverAddress");
82
+ return {
83
+ domain: personalServerRegistrationDomain(input),
84
+ types: import_eip712.SERVER_REGISTRATION_TYPES,
85
+ primaryType: "ServerRegistration",
86
+ message: {
87
+ ownerAddress: input.ownerAddress,
88
+ serverAddress: input.serverAddress,
89
+ publicKey: input.serverPublicKey,
90
+ serverUrl: input.serverUrl
91
+ }
92
+ };
93
+ }
94
+ async function buildPersonalServerRegistrationSignature(input) {
95
+ const typedData = buildPersonalServerRegistrationTypedData({
96
+ ownerAddress: input.signer.address,
97
+ serverAddress: input.serverAddress,
98
+ serverPublicKey: input.serverPublicKey,
99
+ serverUrl: input.serverUrl,
100
+ config: input.config,
101
+ chainId: input.chainId,
102
+ verifyingContract: input.verifyingContract
103
+ });
104
+ const signature = await input.signer.signTypedData(typedData);
105
+ return {
106
+ signature,
107
+ signerAddress: input.signer.address,
108
+ typedData
109
+ };
110
+ }
111
+ const registerPersonalServerSignature = buildPersonalServerRegistrationSignature;
112
+ // Annotate the CommonJS export names for ESM import in node:
113
+ 0 && (module.exports = {
114
+ PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID,
115
+ PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT,
116
+ buildPersonalServerRegistrationSignature,
117
+ buildPersonalServerRegistrationTypedData,
118
+ createViemPersonalServerRegistrationSigner,
119
+ personalServerRegistrationDomain,
120
+ registerPersonalServerSignature
121
+ });
122
+ //# sourceMappingURL=personal-server-registration.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/protocol/personal-server-registration.ts"],"sourcesContent":["/**\n * Personal Server registration typed-data and signing helpers.\n *\n * These helpers are protocol-owned and runtime-neutral. Apps can sign with\n * viem local accounts, wallet clients, Account products, or any equivalent\n * signer by adapting to {@link PersonalServerRegistrationSigner}.\n *\n * @category Protocol\n */\n\nimport {\n isAddress,\n type Account,\n type Address,\n type Hex,\n type TypedDataDomain,\n type TypedDataDefinition,\n} from \"viem\";\nimport {\n SERVER_REGISTRATION_TYPES,\n serverRegistrationDomain,\n type DataPortabilityGatewayConfig,\n type ServerRegistrationMessage,\n} from \"./eip712\";\n\nexport const PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID = 1480;\nexport const PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT =\n \"0x1483B1F634DBA75AeaE60da7f01A679aabd5ee2c\" as const;\n\nexport type PersonalServerRegistrationTypedData = TypedDataDefinition<\n typeof SERVER_REGISTRATION_TYPES,\n \"ServerRegistration\"\n> & {\n message: ServerRegistrationMessage;\n};\n\nexport interface PersonalServerRegistrationSigner {\n address: Address;\n signTypedData(\n typedData: PersonalServerRegistrationTypedData,\n ): Promise<Hex> | Hex;\n}\n\nexport interface ViemPersonalServerRegistrationWalletClient {\n account?: Account | Address | null;\n signTypedData(\n typedData: PersonalServerRegistrationTypedData & {\n account?: Account | Address;\n },\n ): Promise<Hex>;\n}\n\nexport type ViemPersonalServerRegistrationSignerSource =\n | PersonalServerRegistrationSigner\n | ViemPersonalServerRegistrationWalletClient;\n\nexport interface BuildPersonalServerRegistrationTypedDataInput {\n ownerAddress: Address;\n serverAddress: Address;\n serverPublicKey: string;\n serverUrl: string;\n config?: DataPortabilityGatewayConfig;\n chainId?: number;\n verifyingContract?: Address;\n}\n\nexport interface BuildPersonalServerRegistrationSignatureInput {\n signer: PersonalServerRegistrationSigner;\n serverAddress: Address;\n serverPublicKey: string;\n serverUrl: string;\n config?: DataPortabilityGatewayConfig;\n chainId?: number;\n verifyingContract?: Address;\n}\n\nexport interface PersonalServerRegistrationSignature {\n signature: Hex;\n signerAddress: Address;\n typedData: PersonalServerRegistrationTypedData;\n}\n\nexport interface PersonalServerRegistrationDomainInput {\n config?: DataPortabilityGatewayConfig;\n chainId?: number;\n verifyingContract?: Address;\n}\n\nfunction assertAddress(value: Address, name: string): void {\n if (!isAddress(value)) {\n throw new Error(`${name} must be a valid EVM address`);\n }\n}\n\nfunction getAccountAddress(\n account: Account | Address | null | undefined,\n): Address | undefined {\n if (!account) {\n return undefined;\n }\n\n return typeof account === \"string\" ? account : account.address;\n}\n\nfunction isPersonalServerRegistrationSigner(\n source: ViemPersonalServerRegistrationSignerSource,\n): source is PersonalServerRegistrationSigner {\n return \"address\" in source && typeof source.signTypedData === \"function\";\n}\n\nexport function createViemPersonalServerRegistrationSigner(\n source: ViemPersonalServerRegistrationSignerSource,\n options: { account?: Account | Address } = {},\n): PersonalServerRegistrationSigner {\n if (isPersonalServerRegistrationSigner(source)) {\n return source;\n }\n\n const accountAddress =\n getAccountAddress(options.account) ?? getAccountAddress(source.account);\n\n if (accountAddress) {\n return {\n address: accountAddress,\n signTypedData: (typedData) =>\n source.signTypedData({\n ...typedData,\n account: options.account ?? source.account ?? accountAddress,\n }),\n };\n }\n\n throw new Error(\n \"Viem wallet client requires an account option or account property\",\n );\n}\n\nexport function personalServerRegistrationDomain(\n input: PersonalServerRegistrationDomainInput = {},\n): TypedDataDomain {\n if (input.config) {\n return serverRegistrationDomain(input.config);\n }\n\n const verifyingContract =\n input.verifyingContract ??\n PERSONAL_SERVER_REGISTRATION_DEFAULT_VERIFYING_CONTRACT;\n assertAddress(verifyingContract, \"verifyingContract\");\n\n return {\n name: \"Vana Data Portability\",\n version: \"1\",\n chainId: input.chainId ?? PERSONAL_SERVER_REGISTRATION_DEFAULT_CHAIN_ID,\n verifyingContract,\n };\n}\n\nexport function buildPersonalServerRegistrationTypedData(\n input: BuildPersonalServerRegistrationTypedDataInput,\n): PersonalServerRegistrationTypedData {\n assertAddress(input.ownerAddress, \"ownerAddress\");\n assertAddress(input.serverAddress, \"serverAddress\");\n\n return {\n domain: personalServerRegistrationDomain(input),\n types: SERVER_REGISTRATION_TYPES,\n primaryType: \"ServerRegistration\",\n message: {\n ownerAddress: input.ownerAddress,\n serverAddress: input.serverAddress,\n publicKey: input.serverPublicKey,\n serverUrl: input.serverUrl,\n },\n };\n}\n\nexport async function buildPersonalServerRegistrationSignature(\n input: BuildPersonalServerRegistrationSignatureInput,\n): Promise<PersonalServerRegistrationSignature> {\n const typedData = buildPersonalServerRegistrationTypedData({\n ownerAddress: input.signer.address,\n serverAddress: input.serverAddress,\n serverPublicKey: input.serverPublicKey,\n serverUrl: input.serverUrl,\n config: input.config,\n chainId: input.chainId,\n verifyingContract: input.verifyingContract,\n });\n const signature = await input.signer.signTypedData(typedData);\n\n return {\n signature,\n signerAddress: input.signer.address,\n typedData,\n };\n}\n\nexport const registerPersonalServerSignature =\n buildPersonalServerRegistrationSignature;\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUA,kBAOO;AACP,oBAKO;AAEA,MAAM,gDAAgD;AACtD,MAAM,0DACX;AA6DF,SAAS,cAAc,OAAgB,MAAoB;AACzD,MAAI,KAAC,uBAAU,KAAK,GAAG;AACrB,UAAM,IAAI,MAAM,GAAG,IAAI,8BAA8B;AAAA,EACvD;AACF;AAEA,SAAS,kBACP,SACqB;AACrB,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,YAAY,WAAW,UAAU,QAAQ;AACzD;AAEA,SAAS,mCACP,QAC4C;AAC5C,SAAO,aAAa,UAAU,OAAO,OAAO,kBAAkB;AAChE;AAEO,SAAS,2CACd,QACA,UAA2C,CAAC,GACV;AAClC,MAAI,mCAAmC,MAAM,GAAG;AAC9C,WAAO;AAAA,EACT;AAEA,QAAM,iBACJ,kBAAkB,QAAQ,OAAO,KAAK,kBAAkB,OAAO,OAAO;AAExE,MAAI,gBAAgB;AAClB,WAAO;AAAA,MACL,SAAS;AAAA,MACT,eAAe,CAAC,cACd,OAAO,cAAc;AAAA,QACnB,GAAG;AAAA,QACH,SAAS,QAAQ,WAAW,OAAO,WAAW;AAAA,MAChD,CAAC;AAAA,IACL;AAAA,EACF;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAEO,SAAS,iCACd,QAA+C,CAAC,GAC/B;AACjB,MAAI,MAAM,QAAQ;AAChB,eAAO,wCAAyB,MAAM,MAAM;AAAA,EAC9C;AAEA,QAAM,oBACJ,MAAM,qBACN;AACF,gBAAc,mBAAmB,mBAAmB;AAEpD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IACT,SAAS,MAAM,WAAW;AAAA,IAC1B;AAAA,EACF;AACF;AAEO,SAAS,yCACd,OACqC;AACrC,gBAAc,MAAM,cAAc,cAAc;AAChD,gBAAc,MAAM,eAAe,eAAe;AAElD,SAAO;AAAA,IACL,QAAQ,iCAAiC,KAAK;AAAA,IAC9C,OAAO;AAAA,IACP,aAAa;AAAA,IACb,SAAS;AAAA,MACP,cAAc,MAAM;AAAA,MACpB,eAAe,MAAM;AAAA,MACrB,WAAW,MAAM;AAAA,MACjB,WAAW,MAAM;AAAA,IACnB;AAAA,EACF;AACF;AAEA,eAAsB,yCACpB,OAC8C;AAC9C,QAAM,YAAY,yCAAyC;AAAA,IACzD,cAAc,MAAM,OAAO;AAAA,IAC3B,eAAe,MAAM;AAAA,IACrB,iBAAiB,MAAM;AAAA,IACvB,WAAW,MAAM;AAAA,IACjB,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,IACf,mBAAmB,MAAM;AAAA,EAC3B,CAAC;AACD,QAAM,YAAY,MAAM,MAAM,OAAO,cAAc,SAAS;AAE5D,SAAO;AAAA,IACL;AAAA,IACA,eAAe,MAAM,OAAO;AAAA,IAC5B;AAAA,EACF;AACF;AAEO,MAAM,kCACX;","names":[]}