@partylayer/conformance-runner 0.2.10 → 0.2.12

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.
@@ -6,6 +6,15 @@ import { CIP0103Provider } from '@partylayer/core';
6
6
  * Validates that a Provider implementation conforms to CIP-0103:
7
7
  * - Interface shape (request, on, emit, removeListener)
8
8
  * - All 10 mandatory methods are handled
9
+ *
10
+ * "Mandatory" means the specification's synchronous method table, and nothing
11
+ * else. It iterates CIP0103_MANDATORY_METHODS, which is written out explicitly
12
+ * rather than derived from CIP0103_METHODS: this SDK speaks one method the
13
+ * standard does not define (prepareExecuteAndWait, from the upstream client),
14
+ * and that method is DELIBERATELY EXCLUDED here. A vendor running this suite
15
+ * reads its output as a list of their obligations, so an extension of ours
16
+ * appearing in it would tell them the standard requires something it does not.
17
+ * See the comment on CIP0103_MANDATORY_METHODS in @partylayer/core.
9
18
  * - Event subscription returns Provider for chaining
10
19
  * - Error responses use ProviderRpcError with numeric codes
11
20
  *
@@ -33,11 +33,12 @@ async function runCIP0103ConformanceTests(provider) {
33
33
  });
34
34
  } catch (err) {
35
35
  const isValidError = isNumericCodeError(err);
36
+ const unsupported = isValidError && (err.code === 4200 || err.code === -32601);
36
37
  results.push({
37
38
  name: `Method "${method}" is handled`,
38
39
  category: "method",
39
- passed: isValidError,
40
- error: isValidError ? void 0 : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,
40
+ passed: isValidError && !unsupported,
41
+ error: unsupported ? "A mandatory method cannot be unsupported" : isValidError ? void 0 : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,
41
42
  details: isValidError ? { code: err.code } : void 0
42
43
  });
43
44
  }
@@ -99,6 +100,8 @@ async function runCIP0103ConformanceTests(provider) {
99
100
  const txHandler = (...args) => txEvents.push(...args);
100
101
  provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);
101
102
  try {
103
+ const connected = await provider.request({ method: "connect" });
104
+ if (connected?.isConnected !== true) throw new Error("Wallet connection is required for lifecycle checks");
102
105
  await provider.request({
103
106
  method: "prepareExecute",
104
107
  params: { tx: { _conformance: true } }
@@ -183,7 +186,7 @@ async function runCIP0103ConformanceTests(provider) {
183
186
  passed: true
184
187
  });
185
188
  } catch (err) {
186
- const isHandled = isNumericCodeError(err);
189
+ const isHandled = isNumericCodeError(err) && err.code !== 4200 && err.code !== -32601;
187
190
  results.push({
188
191
  name: "ledgerApi is handled (returns result or ProviderRpcError)",
189
192
  category: "method",
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cip0103-tests.ts"],"names":[],"mappings":";;;AAqCA,eAAsB,2BACpB,QAAA,EACmC;AACnC,EAAA,MAAM,UAA+B,EAAC;AAItC,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,+BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,OAAA,KAAY;AAAA,GACrC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,0BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,EAAA,KAAO;AAAA,GAChC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,4BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,IAAA,KAAS;AAAA,GAClC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,sCAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,cAAA,KAAmB;AAAA,GAC5C,CAAA;AAID,EAAA,KAAA,MAAW,UAAU,yBAAA,EAA2B;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,OAAA,CAAQ,EAAE,QAAQ,MAAA,EAAQ,IAAI,CAAA;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,WAAW,MAAM,CAAA,YAAA,CAAA;AAAA,QACvB,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH,SAAS,GAAA,EAAc;AAGrB,MAAA,MAAM,YAAA,GAAe,mBAAmB,GAAG,CAAA;AAC3C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,WAAW,MAAM,CAAA,YAAA,CAAA;AAAA,QACvB,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,YAAA;AAAA,QACR,OAAO,YAAA,GACH,MAAA,GACA,CAAA,kDAAA,EAAqD,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,QACpE,SAAS,YAAA,GACL,EAAE,IAAA,EAAO,GAAA,CAAyB,MAAK,GACvC;AAAA,OACL,CAAA;AAAA,IACH;AAAA,EACF;AAIA,EAAA,MAAM,cAAc,MAAM;AAAA,EAAC,CAAA;AAE3B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,EAAA,CAAG,eAAA,EAAiB,WAAW,CAAA;AACzD,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,oCAAA;AAAA,IACN,QAAA,EAAU,OAAA;AAAA,IACV,QAAQ,QAAA,KAAa,QAAA;AAAA,IACrB,KAAA,EACE,QAAA,KAAa,QAAA,GACT,MAAA,GACA;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,cAAA,CAAe,eAAA,EAAiB,WAAW,CAAA;AACzE,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,gDAAA;AAAA,IACN,QAAA,EAAU,OAAA;AAAA,IACV,QAAQ,YAAA,KAAiB,QAAA;AAAA,IACzB,KAAA,EACE,YAAA,KAAiB,QAAA,GACb,MAAA,GACA;AAAA,GACP,CAAA;AAID,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,CAAS,OAAA,CAAQ,EAAE,MAAA,EAAQ,uCAAuC,CAAA;AACxE,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,6CAAA;AAAA,MACN,QAAA,EAAU,OAAA;AAAA,MACV,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AACrB,IAAA,MAAM,cAAA,GAAiB,mBAAmB,GAAG,CAAA;AAC7C,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,oDAAA;AAAA,MACN,QAAA,EAAU,OAAA;AAAA,MACV,MAAA,EAAQ,cAAA;AAAA,MACR,OAAO,cAAA,GACH,MAAA,GACA,CAAA,4BAAA,EAA+B,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,MAC9C,SAAS,cAAA,GACL,EAAE,IAAA,EAAO,GAAA,CAAyB,MAAK,GACvC;AAAA,KACL,CAAA;AAED,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,MAAM,OAAQ,GAAA,CAAyB,IAAA;AAEvC,MAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,MAAA;AAChD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,6CAAA;AAAA,QACN,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,aAAA,GACH,MAAA,GACA,CAAA,kCAAA,EAAqC,IAAI,CAAA,CAAA;AAAA,QAC7C,OAAA,EAAS,EAAE,IAAA;AAAK,OACjB,CAAA;AAAA,IACH;AAAA,EACF;AAIA,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,IAAA,CAAK,8BAA8B,CAAA;AAC/D,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,wBAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,UAAA,KAAe,SAAA;AAAA,IAC9B,OACE,OAAO,UAAA,KAAe,YAClB,MAAA,GACA,CAAA,gBAAA,EAAmB,OAAO,UAAU,CAAA;AAAA,GAC3C,CAAA;AAID,EAAA;AACE,IAAA,MAAM,WAAsB,EAAC;AAC7B,IAAA,MAAM,YAAY,CAAA,GAAI,IAAA,KAAoB,QAAA,CAAS,IAAA,CAAK,GAAG,IAAI,CAAA;AAC/D,IAAA,QAAA,CAAS,EAAA,CAAG,cAAA,CAAe,UAAA,EAAY,SAAS,CAAA;AAEhD,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,OAAA,CAAQ;AAAA,QACrB,MAAA,EAAQ,gBAAA;AAAA,QACR,QAAQ,EAAE,EAAA,EAAI,EAAE,YAAA,EAAc,MAAK;AAAE,OACtC,CAAA;AAGD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,+CAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,QAAQ,QAAA,CAAS,IAAA;AAAA,UACf,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,SAC1F;AAAA,QACA,KAAA,EAAO,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,6BAAA,GAAgC,KAAA;AAAA,OAChE,CAAA;AAGD,MAAA,MAAM,cAAc,QAAA,CAAS,IAAA;AAAA,QAC3B,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,OAC1F;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,8CAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ,CAAC,CAAC;AAAA,OACX,CAAA;AAGD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,UAAU,WAAA,CAAY,OAAA;AAC5B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,6CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,SAAA,KAAc;AAAA,SACvC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,4CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,KAAa;AAAA,SACtC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,yCAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,KAAA,KAAU;AAAA,SACnC,CAAA;AAAA,MACH;AAGA,MAAA,MAAM,cAAc,QAAA,CAAS,IAAA;AAAA,QAC3B,CAAC,CAAA,KACC,OAAO,CAAA,KAAM,QAAA,IACb,CAAA,KAAM,IAAA,KACJ,CAAA,CAA8B,MAAA,KAAW,UAAA,IACxC,CAAA,CAA8B,MAAA,KAAW,QAAA;AAAA,OAChD;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,+DAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AAGD,MAAA,MAAM,gBAAgB,QAAA,CAAS,IAAA;AAAA,QAC7B,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,OAC1F;AACA,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,8CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,KAAa;AAAA,SACtC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,sDAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,gBAAA,KAAqB;AAAA,SAC9C,CAAA;AAAA,MACH;AAAA,IACF,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,uDAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ,SAAS,MAAA,GAAS,CAAA;AAAA,QAC1B,KAAA,EAAO,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,0CAAA,GAA6C;AAAA,OAC7E,CAAA;AAAA,IACH,CAAA,SAAE;AACA,MAAA,QAAA,CAAS,cAAA,CAAe,cAAA,CAAe,UAAA,EAAY,SAAS,CAAA;AAAA,IAC9D;AAAA,EACF;AAIA,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,OAAA,CAAQ;AAAA,MACrB,MAAA,EAAQ,WAAA;AAAA,MACR,MAAA,EAAQ,EAAE,aAAA,EAAe,KAAA,EAAO,UAAU,eAAA;AAAgB,KAC3D,CAAA;AACD,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,sCAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AAErB,IAAA,MAAM,SAAA,GAAY,mBAAmB,GAAG,CAAA;AACxC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,2DAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,SAAA;AAAA,MACR,OAAO,SAAA,GAAY,MAAA,GAAY,CAAA,uBAAA,EAA0B,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,KACrE,CAAA;AAAA,EACH;AAIA,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA;AAC/C,EAAA,OAAO;AAAA,IACL,OAAO,OAAA,CAAQ,MAAA;AAAA,IACf,MAAA;AAAA,IACA,MAAA,EAAQ,QAAQ,MAAA,GAAS,MAAA;AAAA,IACzB;AAAA,GACF;AACF;AAIA,SAAS,mBAAmB,GAAA,EAAuB;AACjD,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,MAAM,OAAO,KAAA;AACpD,EAAA,OAAO,OAAQ,IAAgC,IAAA,KAAS,QAAA;AAC1D;AAIO,SAAS,oBAAoB,MAAA,EAA0C;AAC5E,EAAA,MAAM,KAAA,GAAkB;AAAA,IACtB,mEAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA,OAAA,EAAU,OAAO,KAAK,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA,CAAA;AAAA,IAC1E;AAAA,GACF;AAEA,EAAA,MAAM,aAAa,CAAC,WAAA,EAAa,QAAA,EAAU,OAAA,EAAS,SAAS,WAAW,CAAA;AACxE,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,MAAM,UAAA,GAAa,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,GAAG,CAAA;AAClE,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC7B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAM,GAAA,CAAI,WAAA,EAAa,CAAA,aAAA,CAAK,CAAA;AACvC,IAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,MAAA,MAAM,IAAA,GAAO,CAAA,CAAE,MAAA,GAAS,QAAA,GAAM,QAAA;AAC9B,MAAA,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA;AAChC,MAAA,IAAI,EAAE,KAAA,EAAO;AACX,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAS,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA;AAAA,MAC/B;AAAA,IACF;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB","file":"cip0103-tests.js","sourcesContent":["/**\n * CIP-0103 Conformance Test Suite\n *\n * Validates that a Provider implementation conforms to CIP-0103:\n * - Interface shape (request, on, emit, removeListener)\n * - All 10 mandatory methods are handled\n * - Event subscription returns Provider for chaining\n * - Error responses use ProviderRpcError with numeric codes\n *\n * This suite can be run against:\n * - PartyLayerProvider (native path)\n * - createProviderBridge() (bridge path)\n * - Any third-party CIP-0103 Provider\n */\n\nimport type { CIP0103Provider } from '@partylayer/core';\nimport { CIP0103_MANDATORY_METHODS, CIP0103_EVENTS } from '@partylayer/core';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CIP0103TestResult {\n name: string;\n category: 'interface' | 'method' | 'event' | 'error' | 'lifecycle';\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface CIP0103ConformanceReport {\n total: number;\n passed: number;\n failed: number;\n results: CIP0103TestResult[];\n}\n\n// ─── Runner ─────────────────────────────────────────────────────────────────\n\nexport async function runCIP0103ConformanceTests(\n provider: CIP0103Provider,\n): Promise<CIP0103ConformanceReport> {\n const results: CIP0103TestResult[] = [];\n\n // ── Interface shape tests ─────────────────────────────────────────────\n\n results.push({\n name: 'Provider has request() method',\n category: 'interface',\n passed: typeof provider.request === 'function',\n });\n\n results.push({\n name: 'Provider has on() method',\n category: 'interface',\n passed: typeof provider.on === 'function',\n });\n\n results.push({\n name: 'Provider has emit() method',\n category: 'interface',\n passed: typeof provider.emit === 'function',\n });\n\n results.push({\n name: 'Provider has removeListener() method',\n category: 'interface',\n passed: typeof provider.removeListener === 'function',\n });\n\n // ── Method presence tests ─────────────────────────────────────────────\n\n for (const method of CIP0103_MANDATORY_METHODS) {\n try {\n await provider.request({ method, params: {} });\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // A valid ProviderRpcError means the method IS handled\n // (it just may not be authorized / connected yet)\n const isValidError = isNumericCodeError(err);\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: isValidError,\n error: isValidError\n ? undefined\n : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,\n details: isValidError\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n }\n }\n\n // ── Event chaining tests ──────────────────────────────────────────────\n\n const noopHandler = () => {};\n\n const onResult = provider.on('statusChanged', noopHandler);\n results.push({\n name: 'on() returns Provider for chaining',\n category: 'event',\n passed: onResult === provider,\n error:\n onResult === provider\n ? undefined\n : 'on() did not return the Provider instance',\n });\n\n const removeResult = provider.removeListener('statusChanged', noopHandler);\n results.push({\n name: 'removeListener() returns Provider for chaining',\n category: 'event',\n passed: removeResult === provider,\n error:\n removeResult === provider\n ? undefined\n : 'removeListener() did not return the Provider instance',\n });\n\n // ── Error code validation ─────────────────────────────────────────────\n\n try {\n await provider.request({ method: '__cip0103_conformance_nonexistent__' });\n results.push({\n name: 'Unsupported method returns ProviderRpcError',\n category: 'error',\n passed: false,\n error: 'Expected error for unsupported method, got success',\n });\n } catch (err: unknown) {\n const hasNumericCode = isNumericCodeError(err);\n results.push({\n name: 'Unsupported method returns error with numeric code',\n category: 'error',\n passed: hasNumericCode,\n error: hasNumericCode\n ? undefined\n : `Expected numeric code, got: ${String(err)}`,\n details: hasNumericCode\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n\n if (hasNumericCode) {\n const code = (err as { code: number }).code;\n // Should be 4200 (UNSUPPORTED_METHOD) or -32601 (METHOD_NOT_FOUND)\n const isCorrectCode = code === 4200 || code === -32601;\n results.push({\n name: 'Unsupported method uses code 4200 or -32601',\n category: 'error',\n passed: isCorrectCode,\n error: isCorrectCode\n ? undefined\n : `Expected code 4200 or -32601, got ${code}`,\n details: { code },\n });\n }\n }\n\n // ── emit() returns boolean ────────────────────────────────────────────\n\n const emitResult = provider.emit('__cip0103_conformance_test__');\n results.push({\n name: 'emit() returns boolean',\n category: 'interface',\n passed: typeof emitResult === 'boolean',\n error:\n typeof emitResult === 'boolean'\n ? undefined\n : `emit() returned ${typeof emitResult}`,\n });\n\n // ── Transaction lifecycle tests ─────────────────────────────────────\n\n {\n const txEvents: unknown[] = [];\n const txHandler = (...args: unknown[]) => txEvents.push(...args);\n provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);\n\n try {\n await provider.request({\n method: 'prepareExecute',\n params: { tx: { _conformance: true } },\n });\n\n // Check that 'pending' was emitted\n results.push({\n name: 'prepareExecute emits txChanged with \"pending\"',\n category: 'lifecycle',\n passed: txEvents.some(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'pending',\n ),\n error: txEvents.length === 0 ? 'No txChanged events emitted' : undefined,\n });\n\n // Check that 'signed' was emitted\n const signedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'signed',\n ) as Record<string, unknown> | undefined;\n results.push({\n name: 'prepareExecute emits txChanged with \"signed\"',\n category: 'lifecycle',\n passed: !!signedEvent,\n });\n\n // Validate 'signed' payload shape\n if (signedEvent) {\n const payload = signedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'signed event has payload.signature (string)',\n category: 'lifecycle',\n passed: typeof payload?.signature === 'string',\n });\n results.push({\n name: 'signed event has payload.signedBy (string)',\n category: 'lifecycle',\n passed: typeof payload?.signedBy === 'string',\n });\n results.push({\n name: 'signed event has payload.party (string)',\n category: 'lifecycle',\n passed: typeof payload?.party === 'string',\n });\n }\n\n // Check that a terminal state was reached\n const hasTerminal = txEvents.some(\n (e) =>\n typeof e === 'object' &&\n e !== null &&\n ((e as Record<string, unknown>).status === 'executed' ||\n (e as Record<string, unknown>).status === 'failed'),\n );\n results.push({\n name: 'prepareExecute reaches terminal tx state (executed or failed)',\n category: 'lifecycle',\n passed: hasTerminal,\n });\n\n // Validate 'executed' payload shape\n const executedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'executed',\n ) as Record<string, unknown> | undefined;\n if (executedEvent) {\n const payload = executedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'executed event has payload.updateId (string)',\n category: 'lifecycle',\n passed: typeof payload?.updateId === 'string',\n });\n results.push({\n name: 'executed event has payload.completionOffset (number)',\n category: 'lifecycle',\n passed: typeof payload?.completionOffset === 'number',\n });\n }\n } catch {\n // prepareExecute may throw — still check if events were emitted\n results.push({\n name: 'prepareExecute emits txChanged events (despite error)',\n category: 'lifecycle',\n passed: txEvents.length > 0,\n error: txEvents.length === 0 ? 'No txChanged events emitted before error' : undefined,\n });\n } finally {\n provider.removeListener(CIP0103_EVENTS.TX_CHANGED, txHandler);\n }\n }\n\n // ── ledgerApi handling test ────────────────────────────────────────\n\n try {\n await provider.request({\n method: 'ledgerApi',\n params: { requestMethod: 'GET', resource: '/v1/state/acs' },\n });\n results.push({\n name: 'ledgerApi returns result (supported)',\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // ProviderRpcError with numeric code = method is recognized\n const isHandled = isNumericCodeError(err);\n results.push({\n name: 'ledgerApi is handled (returns result or ProviderRpcError)',\n category: 'method',\n passed: isHandled,\n error: isHandled ? undefined : `Unexpected error type: ${String(err)}`,\n });\n }\n\n // ── Summary ───────────────────────────────────────────────────────────\n\n const passed = results.filter((r) => r.passed).length;\n return {\n total: results.length,\n passed,\n failed: results.length - passed,\n results,\n };\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction isNumericCodeError(err: unknown): boolean {\n if (typeof err !== 'object' || err === null) return false;\n return typeof (err as Record<string, unknown>).code === 'number';\n}\n\n// ─── Formatting ─────────────────────────────────────────────────────────────\n\nexport function formatCIP0103Report(report: CIP0103ConformanceReport): string {\n const lines: string[] = [\n '═══ CIP-0103 Conformance Report ═══',\n '',\n `Total: ${report.total} Passed: ${report.passed} Failed: ${report.failed}`,\n '',\n ];\n\n const categories = ['interface', 'method', 'event', 'error', 'lifecycle'] as const;\n for (const cat of categories) {\n const catResults = report.results.filter((r) => r.category === cat);\n if (catResults.length === 0) continue;\n lines.push(`── ${cat.toUpperCase()} ──`);\n for (const r of catResults) {\n const icon = r.passed ? '✓' : '✗';\n lines.push(` ${icon} ${r.name}`);\n if (r.error) {\n lines.push(` → ${r.error}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n"]}
1
+ {"version":3,"sources":["../src/cip0103-tests.ts"],"names":[],"mappings":"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","file":"cip0103-tests.js","sourcesContent":["/**\n * CIP-0103 Conformance Test Suite\n *\n * Validates that a Provider implementation conforms to CIP-0103:\n * - Interface shape (request, on, emit, removeListener)\n * - All 10 mandatory methods are handled\n *\n * \"Mandatory\" means the specification's synchronous method table, and nothing\n * else. It iterates CIP0103_MANDATORY_METHODS, which is written out explicitly\n * rather than derived from CIP0103_METHODS: this SDK speaks one method the\n * standard does not define (prepareExecuteAndWait, from the upstream client),\n * and that method is DELIBERATELY EXCLUDED here. A vendor running this suite\n * reads its output as a list of their obligations, so an extension of ours\n * appearing in it would tell them the standard requires something it does not.\n * See the comment on CIP0103_MANDATORY_METHODS in @partylayer/core.\n * - Event subscription returns Provider for chaining\n * - Error responses use ProviderRpcError with numeric codes\n *\n * This suite can be run against:\n * - PartyLayerProvider (native path)\n * - createProviderBridge() (bridge path)\n * - Any third-party CIP-0103 Provider\n */\n\nimport type { CIP0103Provider } from '@partylayer/core';\nimport { CIP0103_MANDATORY_METHODS, CIP0103_EVENTS } from '@partylayer/core';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CIP0103TestResult {\n name: string;\n category: 'interface' | 'method' | 'event' | 'error' | 'lifecycle';\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface CIP0103ConformanceReport {\n total: number;\n passed: number;\n failed: number;\n results: CIP0103TestResult[];\n}\n\n// ─── Runner ─────────────────────────────────────────────────────────────────\n\nexport async function runCIP0103ConformanceTests(\n provider: CIP0103Provider,\n): Promise<CIP0103ConformanceReport> {\n const results: CIP0103TestResult[] = [];\n\n // ── Interface shape tests ─────────────────────────────────────────────\n\n results.push({\n name: 'Provider has request() method',\n category: 'interface',\n passed: typeof provider.request === 'function',\n });\n\n results.push({\n name: 'Provider has on() method',\n category: 'interface',\n passed: typeof provider.on === 'function',\n });\n\n results.push({\n name: 'Provider has emit() method',\n category: 'interface',\n passed: typeof provider.emit === 'function',\n });\n\n results.push({\n name: 'Provider has removeListener() method',\n category: 'interface',\n passed: typeof provider.removeListener === 'function',\n });\n\n // ── Method presence tests ─────────────────────────────────────────────\n\n for (const method of CIP0103_MANDATORY_METHODS) {\n try {\n await provider.request({ method, params: {} });\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // A valid ProviderRpcError means the method IS handled\n // (it just may not be authorized / connected yet)\n const isValidError = isNumericCodeError(err);\n const unsupported = isValidError && (err.code === 4200 || err.code === -32601);\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: isValidError && !unsupported,\n error: unsupported ? 'A mandatory method cannot be unsupported' : isValidError\n ? undefined\n : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,\n details: isValidError\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n }\n }\n\n // ── Event chaining tests ──────────────────────────────────────────────\n\n const noopHandler = () => {};\n\n const onResult = provider.on('statusChanged', noopHandler);\n results.push({\n name: 'on() returns Provider for chaining',\n category: 'event',\n passed: onResult === provider,\n error:\n onResult === provider\n ? undefined\n : 'on() did not return the Provider instance',\n });\n\n const removeResult = provider.removeListener('statusChanged', noopHandler);\n results.push({\n name: 'removeListener() returns Provider for chaining',\n category: 'event',\n passed: removeResult === provider,\n error:\n removeResult === provider\n ? undefined\n : 'removeListener() did not return the Provider instance',\n });\n\n // ── Error code validation ─────────────────────────────────────────────\n\n try {\n await provider.request({ method: '__cip0103_conformance_nonexistent__' });\n results.push({\n name: 'Unsupported method returns ProviderRpcError',\n category: 'error',\n passed: false,\n error: 'Expected error for unsupported method, got success',\n });\n } catch (err: unknown) {\n const hasNumericCode = isNumericCodeError(err);\n results.push({\n name: 'Unsupported method returns error with numeric code',\n category: 'error',\n passed: hasNumericCode,\n error: hasNumericCode\n ? undefined\n : `Expected numeric code, got: ${String(err)}`,\n details: hasNumericCode\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n\n if (hasNumericCode) {\n const code = (err as { code: number }).code;\n // Should be 4200 (UNSUPPORTED_METHOD) or -32601 (METHOD_NOT_FOUND)\n const isCorrectCode = code === 4200 || code === -32601;\n results.push({\n name: 'Unsupported method uses code 4200 or -32601',\n category: 'error',\n passed: isCorrectCode,\n error: isCorrectCode\n ? undefined\n : `Expected code 4200 or -32601, got ${code}`,\n details: { code },\n });\n }\n }\n\n // ── emit() returns boolean ────────────────────────────────────────────\n\n const emitResult = provider.emit('__cip0103_conformance_test__');\n results.push({\n name: 'emit() returns boolean',\n category: 'interface',\n passed: typeof emitResult === 'boolean',\n error:\n typeof emitResult === 'boolean'\n ? undefined\n : `emit() returned ${typeof emitResult}`,\n });\n\n // ── Transaction lifecycle tests ─────────────────────────────────────\n\n {\n const txEvents: unknown[] = [];\n const txHandler = (...args: unknown[]) => txEvents.push(...args);\n provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);\n\n try {\n // Method-presence checks include disconnect. Establish authorization again\n // before exercising a write; a disconnected provider must not manufacture\n // transaction events merely to make this suite pass.\n const connected = await provider.request<{ isConnected: boolean }>({ method: 'connect' });\n if (connected?.isConnected !== true) throw new Error('Wallet connection is required for lifecycle checks');\n await provider.request({\n method: 'prepareExecute',\n params: { tx: { _conformance: true } },\n });\n\n // Check that 'pending' was emitted\n results.push({\n name: 'prepareExecute emits txChanged with \"pending\"',\n category: 'lifecycle',\n passed: txEvents.some(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'pending',\n ),\n error: txEvents.length === 0 ? 'No txChanged events emitted' : undefined,\n });\n\n // Check that 'signed' was emitted\n const signedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'signed',\n ) as Record<string, unknown> | undefined;\n results.push({\n name: 'prepareExecute emits txChanged with \"signed\"',\n category: 'lifecycle',\n passed: !!signedEvent,\n });\n\n // Validate 'signed' payload shape\n if (signedEvent) {\n const payload = signedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'signed event has payload.signature (string)',\n category: 'lifecycle',\n passed: typeof payload?.signature === 'string',\n });\n results.push({\n name: 'signed event has payload.signedBy (string)',\n category: 'lifecycle',\n passed: typeof payload?.signedBy === 'string',\n });\n results.push({\n name: 'signed event has payload.party (string)',\n category: 'lifecycle',\n passed: typeof payload?.party === 'string',\n });\n }\n\n // Check that a terminal state was reached\n const hasTerminal = txEvents.some(\n (e) =>\n typeof e === 'object' &&\n e !== null &&\n ((e as Record<string, unknown>).status === 'executed' ||\n (e as Record<string, unknown>).status === 'failed'),\n );\n results.push({\n name: 'prepareExecute reaches terminal tx state (executed or failed)',\n category: 'lifecycle',\n passed: hasTerminal,\n });\n\n // Validate 'executed' payload shape\n const executedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'executed',\n ) as Record<string, unknown> | undefined;\n if (executedEvent) {\n const payload = executedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'executed event has payload.updateId (string)',\n category: 'lifecycle',\n passed: typeof payload?.updateId === 'string',\n });\n results.push({\n name: 'executed event has payload.completionOffset (number)',\n category: 'lifecycle',\n passed: typeof payload?.completionOffset === 'number',\n });\n }\n } catch {\n // prepareExecute may throw — still check if events were emitted\n results.push({\n name: 'prepareExecute emits txChanged events (despite error)',\n category: 'lifecycle',\n passed: txEvents.length > 0,\n error: txEvents.length === 0 ? 'No txChanged events emitted before error' : undefined,\n });\n } finally {\n provider.removeListener(CIP0103_EVENTS.TX_CHANGED, txHandler);\n }\n }\n\n // ── ledgerApi handling test ────────────────────────────────────────\n\n try {\n await provider.request({\n method: 'ledgerApi',\n params: { requestMethod: 'GET', resource: '/v1/state/acs' },\n });\n results.push({\n name: 'ledgerApi returns result (supported)',\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // ProviderRpcError with numeric code = method is recognized\n const isHandled = isNumericCodeError(err) && err.code !== 4200 && err.code !== -32601;\n results.push({\n name: 'ledgerApi is handled (returns result or ProviderRpcError)',\n category: 'method',\n passed: isHandled,\n error: isHandled ? undefined : `Unexpected error type: ${String(err)}`,\n });\n }\n\n // ── Summary ───────────────────────────────────────────────────────────\n\n const passed = results.filter((r) => r.passed).length;\n return {\n total: results.length,\n passed,\n failed: results.length - passed,\n results,\n };\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction isNumericCodeError(err: unknown): err is { code: number } {\n if (typeof err !== 'object' || err === null) return false;\n return typeof (err as Record<string, unknown>).code === 'number';\n}\n\n// ─── Formatting ─────────────────────────────────────────────────────────────\n\nexport function formatCIP0103Report(report: CIP0103ConformanceReport): string {\n const lines: string[] = [\n '═══ CIP-0103 Conformance Report ═══',\n '',\n `Total: ${report.total} Passed: ${report.passed} Failed: ${report.failed}`,\n '',\n ];\n\n const categories = ['interface', 'method', 'event', 'error', 'lifecycle'] as const;\n for (const cat of categories) {\n const catResults = report.results.filter((r) => r.category === cat);\n if (catResults.length === 0) continue;\n lines.push(`── ${cat.toUpperCase()} ──`);\n for (const r of catResults) {\n const icon = r.passed ? '✓' : '✗';\n lines.push(` ${icon} ${r.name}`);\n if (r.error) {\n lines.push(` → ${r.error}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n"]}
package/dist/index.js CHANGED
@@ -54,11 +54,12 @@ async function runCIP0103ConformanceTests(provider) {
54
54
  });
55
55
  } catch (err) {
56
56
  const isValidError = isNumericCodeError(err);
57
+ const unsupported = isValidError && (err.code === 4200 || err.code === -32601);
57
58
  results.push({
58
59
  name: `Method "${method}" is handled`,
59
60
  category: "method",
60
- passed: isValidError,
61
- error: isValidError ? void 0 : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,
61
+ passed: isValidError && !unsupported,
62
+ error: unsupported ? "A mandatory method cannot be unsupported" : isValidError ? void 0 : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,
62
63
  details: isValidError ? { code: err.code } : void 0
63
64
  });
64
65
  }
@@ -120,6 +121,8 @@ async function runCIP0103ConformanceTests(provider) {
120
121
  const txHandler = (...args) => txEvents.push(...args);
121
122
  provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);
122
123
  try {
124
+ const connected = await provider.request({ method: "connect" });
125
+ if (connected?.isConnected !== true) throw new Error("Wallet connection is required for lifecycle checks");
123
126
  await provider.request({
124
127
  method: "prepareExecute",
125
128
  params: { tx: { _conformance: true } }
@@ -204,7 +207,7 @@ async function runCIP0103ConformanceTests(provider) {
204
207
  passed: true
205
208
  });
206
209
  } catch (err) {
207
- const isHandled = isNumericCodeError(err);
210
+ const isHandled = isNumericCodeError(err) && err.code !== 4200 && err.code !== -32601;
208
211
  results.push({
209
212
  name: "ledgerApi is handled (returns result or ProviderRpcError)",
210
213
  category: "method",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cip0103-tests.ts","../src/loader.ts","../src/tests.ts","../src/report.ts","../src/index.ts"],"names":["resolve","runCIP0103ConformanceTests","formatCIP0103Report"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,IAAA,qBAAA,GAAA,EAAA;AAAA,QAAA,CAAA,qBAAA,EAAA;AAAA,EAAA,mBAAA,EAAA,MAAA,mBAAA;AAAA,EAAA,0BAAA,EAAA,MAAA;AAAA,CAAA,CAAA;AAqCA,eAAsB,2BACpB,QAAA,EACmC;AACnC,EAAA,MAAM,UAA+B,EAAC;AAItC,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,+BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,OAAA,KAAY;AAAA,GACrC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,0BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,EAAA,KAAO;AAAA,GAChC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,4BAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,IAAA,KAAS;AAAA,GAClC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,sCAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,QAAA,CAAS,cAAA,KAAmB;AAAA,GAC5C,CAAA;AAID,EAAA,KAAA,MAAW,UAAU,yBAAA,EAA2B;AAC9C,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,OAAA,CAAQ,EAAE,QAAQ,MAAA,EAAQ,IAAI,CAAA;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,WAAW,MAAM,CAAA,YAAA,CAAA;AAAA,QACvB,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AAAA,IACH,SAAS,GAAA,EAAc;AAGrB,MAAA,MAAM,YAAA,GAAe,mBAAmB,GAAG,CAAA;AAC3C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,WAAW,MAAM,CAAA,YAAA,CAAA;AAAA,QACvB,QAAA,EAAU,QAAA;AAAA,QACV,MAAA,EAAQ,YAAA;AAAA,QACR,OAAO,YAAA,GACH,MAAA,GACA,CAAA,kDAAA,EAAqD,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,QACpE,SAAS,YAAA,GACL,EAAE,IAAA,EAAO,GAAA,CAAyB,MAAK,GACvC;AAAA,OACL,CAAA;AAAA,IACH;AAAA,EACF;AAIA,EAAA,MAAM,cAAc,MAAM;AAAA,EAAC,CAAA;AAE3B,EAAA,MAAM,QAAA,GAAW,QAAA,CAAS,EAAA,CAAG,eAAA,EAAiB,WAAW,CAAA;AACzD,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,oCAAA;AAAA,IACN,QAAA,EAAU,OAAA;AAAA,IACV,QAAQ,QAAA,KAAa,QAAA;AAAA,IACrB,KAAA,EACE,QAAA,KAAa,QAAA,GACT,MAAA,GACA;AAAA,GACP,CAAA;AAED,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,cAAA,CAAe,eAAA,EAAiB,WAAW,CAAA;AACzE,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,gDAAA;AAAA,IACN,QAAA,EAAU,OAAA;AAAA,IACV,QAAQ,YAAA,KAAiB,QAAA;AAAA,IACzB,KAAA,EACE,YAAA,KAAiB,QAAA,GACb,MAAA,GACA;AAAA,GACP,CAAA;AAID,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,CAAS,OAAA,CAAQ,EAAE,MAAA,EAAQ,uCAAuC,CAAA;AACxE,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,6CAAA;AAAA,MACN,QAAA,EAAU,OAAA;AAAA,MACV,MAAA,EAAQ,KAAA;AAAA,MACR,KAAA,EAAO;AAAA,KACR,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AACrB,IAAA,MAAM,cAAA,GAAiB,mBAAmB,GAAG,CAAA;AAC7C,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,oDAAA;AAAA,MACN,QAAA,EAAU,OAAA;AAAA,MACV,MAAA,EAAQ,cAAA;AAAA,MACR,OAAO,cAAA,GACH,MAAA,GACA,CAAA,4BAAA,EAA+B,MAAA,CAAO,GAAG,CAAC,CAAA,CAAA;AAAA,MAC9C,SAAS,cAAA,GACL,EAAE,IAAA,EAAO,GAAA,CAAyB,MAAK,GACvC;AAAA,KACL,CAAA;AAED,IAAA,IAAI,cAAA,EAAgB;AAClB,MAAA,MAAM,OAAQ,GAAA,CAAyB,IAAA;AAEvC,MAAA,MAAM,aAAA,GAAgB,IAAA,KAAS,IAAA,IAAQ,IAAA,KAAS,MAAA;AAChD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,6CAAA;AAAA,QACN,QAAA,EAAU,OAAA;AAAA,QACV,MAAA,EAAQ,aAAA;AAAA,QACR,KAAA,EAAO,aAAA,GACH,MAAA,GACA,CAAA,kCAAA,EAAqC,IAAI,CAAA,CAAA;AAAA,QAC7C,OAAA,EAAS,EAAE,IAAA;AAAK,OACjB,CAAA;AAAA,IACH;AAAA,EACF;AAIA,EAAA,MAAM,UAAA,GAAa,QAAA,CAAS,IAAA,CAAK,8BAA8B,CAAA;AAC/D,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,wBAAA;AAAA,IACN,QAAA,EAAU,WAAA;AAAA,IACV,MAAA,EAAQ,OAAO,UAAA,KAAe,SAAA;AAAA,IAC9B,OACE,OAAO,UAAA,KAAe,YAClB,MAAA,GACA,CAAA,gBAAA,EAAmB,OAAO,UAAU,CAAA;AAAA,GAC3C,CAAA;AAID,EAAA;AACE,IAAA,MAAM,WAAsB,EAAC;AAC7B,IAAA,MAAM,YAAY,CAAA,GAAI,IAAA,KAAoB,QAAA,CAAS,IAAA,CAAK,GAAG,IAAI,CAAA;AAC/D,IAAA,QAAA,CAAS,EAAA,CAAG,cAAA,CAAe,UAAA,EAAY,SAAS,CAAA;AAEhD,IAAA,IAAI;AACF,MAAA,MAAM,SAAS,OAAA,CAAQ;AAAA,QACrB,MAAA,EAAQ,gBAAA;AAAA,QACR,QAAQ,EAAE,EAAA,EAAI,EAAE,YAAA,EAAc,MAAK;AAAE,OACtC,CAAA;AAGD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,+CAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,QAAQ,QAAA,CAAS,IAAA;AAAA,UACf,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,SAC1F;AAAA,QACA,KAAA,EAAO,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,6BAAA,GAAgC,KAAA;AAAA,OAChE,CAAA;AAGD,MAAA,MAAM,cAAc,QAAA,CAAS,IAAA;AAAA,QAC3B,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,OAC1F;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,8CAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ,CAAC,CAAC;AAAA,OACX,CAAA;AAGD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,UAAU,WAAA,CAAY,OAAA;AAC5B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,6CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,SAAA,KAAc;AAAA,SACvC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,4CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,KAAa;AAAA,SACtC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,yCAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,KAAA,KAAU;AAAA,SACnC,CAAA;AAAA,MACH;AAGA,MAAA,MAAM,cAAc,QAAA,CAAS,IAAA;AAAA,QAC3B,CAAC,CAAA,KACC,OAAO,CAAA,KAAM,QAAA,IACb,CAAA,KAAM,IAAA,KACJ,CAAA,CAA8B,MAAA,KAAW,UAAA,IACxC,CAAA,CAA8B,MAAA,KAAW,QAAA;AAAA,OAChD;AACA,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,+DAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ;AAAA,OACT,CAAA;AAGD,MAAA,MAAM,gBAAgB,QAAA,CAAS,IAAA;AAAA,QAC7B,CAAC,MAAM,OAAO,CAAA,KAAM,YAAY,CAAA,KAAM,IAAA,IAAS,EAA8B,MAAA,KAAW;AAAA,OAC1F;AACA,MAAA,IAAI,aAAA,EAAe;AACjB,QAAA,MAAM,UAAU,aAAA,CAAc,OAAA;AAC9B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,8CAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,QAAA,KAAa;AAAA,SACtC,CAAA;AACD,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,sDAAA;AAAA,UACN,QAAA,EAAU,WAAA;AAAA,UACV,MAAA,EAAQ,OAAO,OAAA,EAAS,gBAAA,KAAqB;AAAA,SAC9C,CAAA;AAAA,MACH;AAAA,IACF,CAAA,CAAA,MAAQ;AAEN,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,uDAAA;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,MAAA,EAAQ,SAAS,MAAA,GAAS,CAAA;AAAA,QAC1B,KAAA,EAAO,QAAA,CAAS,MAAA,KAAW,CAAA,GAAI,0CAAA,GAA6C;AAAA,OAC7E,CAAA;AAAA,IACH,CAAA,SAAE;AACA,MAAA,QAAA,CAAS,cAAA,CAAe,cAAA,CAAe,UAAA,EAAY,SAAS,CAAA;AAAA,IAC9D;AAAA,EACF;AAIA,EAAA,IAAI;AACF,IAAA,MAAM,SAAS,OAAA,CAAQ;AAAA,MACrB,MAAA,EAAQ,WAAA;AAAA,MACR,MAAA,EAAQ,EAAE,aAAA,EAAe,KAAA,EAAO,UAAU,eAAA;AAAgB,KAC3D,CAAA;AACD,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,sCAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH,SAAS,GAAA,EAAc;AAErB,IAAA,MAAM,SAAA,GAAY,mBAAmB,GAAG,CAAA;AACxC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,2DAAA;AAAA,MACN,QAAA,EAAU,QAAA;AAAA,MACV,MAAA,EAAQ,SAAA;AAAA,MACR,OAAO,SAAA,GAAY,MAAA,GAAY,CAAA,uBAAA,EAA0B,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,KACrE,CAAA;AAAA,EACH;AAIA,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA;AAC/C,EAAA,OAAO;AAAA,IACL,OAAO,OAAA,CAAQ,MAAA;AAAA,IACf,MAAA;AAAA,IACA,MAAA,EAAQ,QAAQ,MAAA,GAAS,MAAA;AAAA,IACzB;AAAA,GACF;AACF;AAIA,SAAS,mBAAmB,GAAA,EAAuB;AACjD,EAAA,IAAI,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,KAAQ,MAAM,OAAO,KAAA;AACpD,EAAA,OAAO,OAAQ,IAAgC,IAAA,KAAS,QAAA;AAC1D;AAIO,SAAS,oBAAoB,MAAA,EAA0C;AAC5E,EAAA,MAAM,KAAA,GAAkB;AAAA,IACtB,mEAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA,OAAA,EAAU,OAAO,KAAK,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA,UAAA,EAAa,OAAO,MAAM,CAAA,CAAA;AAAA,IAC1E;AAAA,GACF;AAEA,EAAA,MAAM,aAAa,CAAC,WAAA,EAAa,QAAA,EAAU,OAAA,EAAS,SAAS,WAAW,CAAA;AACxE,EAAA,KAAA,MAAW,OAAO,UAAA,EAAY;AAC5B,IAAA,MAAM,UAAA,GAAa,OAAO,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,GAAG,CAAA;AAClE,IAAA,IAAI,UAAA,CAAW,WAAW,CAAA,EAAG;AAC7B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,aAAA,EAAM,GAAA,CAAI,WAAA,EAAa,CAAA,aAAA,CAAK,CAAA;AACvC,IAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,MAAA,MAAM,IAAA,GAAO,CAAA,CAAE,MAAA,GAAS,QAAA,GAAM,QAAA;AAC9B,MAAA,KAAA,CAAM,KAAK,CAAA,EAAA,EAAK,IAAI,CAAA,CAAA,EAAI,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA;AAChC,MAAA,IAAI,EAAE,KAAA,EAAO;AACX,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAS,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA;AAAA,MAC/B;AAAA,IACF;AACA,IAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAAA,EACf;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;AAnVA,IAAA,kBAAA,GAAA,KAAA,CAAA;AAAA,EAAA,sBAAA,GAAA;AAAA,EAAA;AAAA,CAAA,CAAA;ACgBA,IAAM,WAAA,GAAc,aAAA,CAAc,MAAA,CAAA,IAAA,CAAY,GAAG,CAAA;AAKjD,eAAsB,YACpB,iBAAA,EACwB;AACxB,EAAA,IAAI,WAAA;AAGJ,EAAA,IAAI,kBAAkB,UAAA,CAAW,GAAG,KAAK,iBAAA,CAAkB,UAAA,CAAW,GAAG,CAAA,EAAG;AAC1E,IAAA,WAAA,GAAc,QAAQ,iBAAiB,CAAA;AAAA,EACzC,CAAA,MAAO;AAEL,IAAA,IAAI;AACF,MAAA,WAAA,GAAc,WAAA,CAAY,QAAQ,iBAAiB,CAAA;AAAA,IACrD,CAAA,CAAA,MAAQ;AACN,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,wBAAA,EAA2B,iBAAiB,CAAA,CAAE,CAAA;AAAA,IAChE;AAAA,EACF;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,aAAA,CAAc,WAAW,CAAA,CAAE,IAAA;AAC7C,IAAA,MAAM,MAAA,GAAS,MAAM,OAAO,SAAA,CAAA;AAG5B,IAAA,MAAM,OAAA,GAAU,OAAO,OAAA,IAAW,MAAA,CAAO,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,CAAC,CAAC,CAAA;AAE/D,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,IAC3C;AAGA,IAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,MAAA,OAAO,IAAI,OAAA,EAAQ;AAAA,IACrB;AAEA,IAAA,OAAO,OAAA;AAAA,EACT,SAAS,GAAA,EAAK;AAEZ,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,YAAY,WAAW,CAAA;AACtC,MAAA,MAAM,OAAA,GAAU,OAAO,OAAA,IAAW,MAAA,CAAO,OAAO,IAAA,CAAK,MAAM,CAAA,CAAE,CAAC,CAAC,CAAA;AAE/D,MAAA,IAAI,CAAC,OAAA,EAAS;AACZ,QAAA,MAAM,IAAI,MAAM,yBAAyB,CAAA;AAAA,MAC3C;AAEA,MAAA,IAAI,OAAO,YAAY,UAAA,EAAY;AACjC,QAAA,OAAO,IAAI,OAAA,EAAQ;AAAA,MACrB;AAEA,MAAA,OAAO,OAAA;AAAA,IACT,SAAS,MAAA,EAAQ;AACf,MAAA,MAAM,IAAI,KAAA;AAAA,QACR,2BAA2B,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA;AAAA,OAC7E;AAAA,IACF;AAAA,EACF;AACF;ACvCO,SAAS,iBAAA,GAAoC;AAClD,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,kBAAA;AAAA,IACT,MAAA,EAAQ,0BAAA;AAAA,IACR,OAAA,EAAS,QAAA;AAAA,IACT,MAAA,EAAQ;AAAA,MACN,OAAO,MAAM;AAAA,MAAC,CAAA;AAAA,MACd,MAAM,MAAM;AAAA,MAAC,CAAA;AAAA,MACb,MAAM,MAAM;AAAA,MAAC,CAAA;AAAA,MACb,OAAO,MAAM;AAAA,MAAC;AAAA,KAChB;AAAA,IACA,SAAA,EAAW,MAAA;AAAA,IACX,QAAA,EAAU;AAAA,MACR,SAAA,EAAW,aAAa,EAAC;AAAA,KAC3B;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,OAAA,EAAS,OAAO,IAAA,KAAiB,IAAA;AAAA,MACjC,OAAA,EAAS,OAAO,IAAA,KAAiB,IAAA;AAAA,MACjC,aAAa,YAAY;AAAA,KAC3B;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAK,YAAY,IAAA;AAAA,MACjB,KAAK,YAAY;AAAA,MAAC,CAAA;AAAA,MAClB,QAAQ,YAAY;AAAA,MAAC,CAAA;AAAA,MACrB,OAAO,YAAY;AAAA,MAAC;AAAA,KACtB;AAAA,IACA,OAAA,EAAS,OAAO,EAAA,KAAe;AAC7B,MAAA,MAAM,IAAI,OAAA,CAAQ,CAACA,aAAY,UAAA,CAAWA,QAAAA,EAAS,EAAE,CAAC,CAAA;AACtD,MAAA,MAAM,IAAI,MAAM,SAAS,CAAA;AAAA,IAC3B;AAAA,GACF;AACF;AAKA,eAAsB,mBAAA,CACpB,SACA,OAAA,EACuB;AACvB,EAAA,MAAM,UAAwB,EAAC;AAG/B,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,sBAAA;AAAA,IACN,QAAQ,OAAO,OAAA,CAAQ,aAAa,QAAA,IAAY,OAAA,CAAQ,SAAS,MAAA,GAAS,CAAA;AAAA,IAC1E,OAAA,EAAS,EAAE,QAAA,EAAU,OAAA,CAAQ,QAAA;AAAS,GACvC,CAAA;AAED,EAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,IACX,IAAA,EAAM,kBAAA;AAAA,IACN,QAAQ,OAAO,OAAA,CAAQ,SAAS,QAAA,IAAY,OAAA,CAAQ,KAAK,MAAA,GAAS,CAAA;AAAA,IAClE,OAAA,EAAS,EAAE,IAAA,EAAM,OAAA,CAAQ,IAAA;AAAK,GAC/B,CAAA;AAGD,EAAA,IAAI,YAAA;AACJ,EAAA,IAAI;AACF,IAAA,YAAA,GAAe,QAAQ,eAAA,EAAgB;AACvC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,+BAAA;AAAA,MACN,MAAA,EAAQ,KAAA,CAAM,OAAA,CAAQ,YAAY,CAAA;AAAA,MAClC,OAAA,EAAS,EAAE,YAAA;AAAa,KACzB,CAAA;AAGD,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,QAAA,CAAS,SAAS,CAAA;AAClD,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,gCAAA;AAAA,MACN,MAAA,EAAQ,UAAA;AAAA,MACR,OAAA,EAAS,EAAE,YAAA;AAAa,KACzB,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,8BAAA;AAAA,MACN,MAAA,EAAQ,KAAA;AAAA,MACR,OAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,KACvD,CAAA;AACD,IAAA,OAAO,OAAA;AAAA,EACT;AAGA,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAAS,MAAM,OAAA,CAAQ,eAAA,EAAgB;AAC7C,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,sCAAA;AAAA,MACN,MAAA,EACE,OAAO,MAAA,KAAW,QAAA,IAClB,OAAO,MAAA,CAAO,SAAA,KAAc,SAAA,KAC3B,MAAA,CAAO,SAAA,IAAa,OAAO,MAAA,CAAO,MAAA,KAAW,QAAA,CAAA;AAAA,MAChD,OAAA,EAAS,EAAE,MAAA;AAAO,KACnB,CAAA;AAAA,EACH,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,8BAAA;AAAA,MACN,MAAA,EAAQ,KAAA;AAAA,MACR,OAAO,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,KACvD,CAAA;AAAA,EACH;AAMA,EAAA,IAAI,YAAA,CAAa,QAAA,CAAS,aAAa,CAAA,EAAG;AACxC,IAAA,IAAI,OAAO,OAAA,CAAQ,WAAA,KAAgB,UAAA,EAAY;AAC7C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,oDAAA;AAAA,QACN,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF,CAAA,MAAO;AAEL,IAAA,IAAI,OAAO,OAAA,CAAQ,WAAA,KAAgB,UAAA,EAAY;AAC7C,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,CAAQ,YAAY,OAAA,EAAS,IAA0B,EAAE,OAAA,EAAS,QAAQ,CAAA;AAChF,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,mEAAA;AAAA,UACN,MAAA,EAAQ,KAAA;AAAA,UACR,KAAA,EAAO;AAAA,SACR,CAAA;AAAA,MACH,SAAS,GAAA,EAAK;AACZ,QAAA,MAAM,SAAS,GAAA,YAAe,2BAAA;AAC9B,QAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,UACX,IAAA,EAAM,mEAAA;AAAA,UACN,MAAA;AAAA,UACA,KAAA,EAAO,SAAS,MAAA,GAAY,GAAA,YAAe,QAAQ,GAAA,CAAI,OAAA,GAAU,OAAO,GAAG;AAAA,SAC5E,CAAA;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,YAAA,CAAa,QAAA,CAAS,iBAAiB,CAAA,EAAG;AAC5C,IAAA,IAAI,OAAO,OAAA,CAAQ,eAAA,KAAoB,UAAA,EAAY;AACjD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,wDAAA;AAAA,QACN,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF;AAEA,EAAA,IAAI,YAAA,CAAa,QAAA,CAAS,mBAAmB,CAAA,EAAG;AAC9C,IAAA,IAAI,OAAO,OAAA,CAAQ,iBAAA,KAAsB,UAAA,EAAY;AACnD,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,0DAAA;AAAA,QACN,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO;AAAA,OACR,CAAA;AAAA,IACH;AAAA,EACF;AAcA,EAAA;AACE,IAAA,MAAM,gBAAA,GAAmB,OAAO,OAAA,CAAQ,OAAA,KAAY,UAAA;AACpD,IAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,QAAA,CAAS,SAAS,CAAA;AACvD,IAAA,IAAI,eAAA,IAAmB,CAAC,gBAAA,EAAkB;AACxC,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,gDAAA;AAAA,QACN,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,gEAAA;AAAA,OACvB,CAAA;AAAA,IACH,CAAA,MAAA,IAAW,gBAAA,IAAoB,CAAC,eAAA,EAAiB;AAC/C,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,wDAAA;AAAA,QACN,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EACE,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,mJAAA;AAAA,OAElB,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,QACX,IAAA,EAAM,sCAAA;AAAA,QACN,MAAA,EAAQ,IAAA;AAAA,QACR,OAAA,EAAS,EAAE,gBAAA,EAAkB,eAAA;AAAgB,OAC9C,CAAA;AAAA,IACH;AAAA,EACF;AAMA,EAAA,OAAO,OAAA;AACT;;;AC3MO,SAAS,cAAA,CACd,OAAA,EACA,KAAA,EACA,SAAA,EACmB;AACnB,EAAA,MAAM,SAAS,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA;AAC7C,EAAA,MAAM,MAAA,GAAS,MAAM,MAAA,CAAO,CAAC,MAAM,CAAC,CAAA,CAAE,MAAM,CAAA,CAAE,MAAA;AAE9C,EAAA,OAAO;AAAA,IACL,OAAA;AAAA,IACA,WAAA,EAAa;AAAA,MACX,aAAa,OAAA,CAAQ,OAAA;AAAA,MACrB,UAAU,OAAA,CAAQ,QAAA;AAAA,MAClB,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,KACpC;AAAA,IACA,OAAA,EAAS;AAAA,MACP,OAAO,KAAA,CAAM,MAAA;AAAA,MACb,MAAA;AAAA,MACA,MAAA;AAAA,MACA,QAAA,EAAU,IAAA,CAAK,GAAA,EAAI,GAAI;AAAA,KACzB;AAAA,IACA;AAAA,GACF;AACF;AAKO,SAAS,iBAAiB,MAAA,EAAmC;AAClE,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,uCAAuC,CAAA;AAClD,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,IAAA,CAAK,YAAY,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,CAAA,CAAG,CAAA;AACzE,EAAA,IAAI,MAAA,CAAO,QAAQ,OAAA,EAAS;AAC1B,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,SAAA,EAAY,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AAAA,EACjD;AACA,EAAA,KAAA,CAAM,IAAA,CAAK,qBAAqB,MAAA,CAAO,WAAA,CAAY,WAAW,CAAA,IAAA,EAAO,MAAA,CAAO,WAAA,CAAY,QAAQ,CAAA,CAAE,CAAA;AAClG,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,WAAA,EAAc,MAAA,CAAO,WAAA,CAAY,SAAS,CAAA,CAAE,CAAA;AACvD,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,KAAK,UAAU,CAAA;AACrB,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,eAAA,EAAkB,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,CAAE,CAAA;AACnD,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,UAAA,EAAa,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAC/C,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,UAAA,EAAa,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAC/C,EAAA,KAAA,CAAM,IAAA,CAAK,CAAA,YAAA,EAAe,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAA,CAAI,CAAA;AACrD,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AACb,EAAA,KAAA,CAAM,KAAK,eAAe,CAAA;AAC1B,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AAEzB,EAAA,MAAA,CAAO,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,KAAA,KAAU;AACpC,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,MAAA,GAAS,QAAA,GAAM,QAAA;AACnC,IAAA,KAAA,CAAM,IAAA,CAAK,GAAG,KAAA,GAAQ,CAAC,KAAK,MAAM,CAAA,CAAA,EAAI,IAAA,CAAK,IAAI,CAAA,CAAE,CAAA;AACjD,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,MAAA,CAAO,OAAA,CAAQ,KAAK,OAAO,CAAA,CAAE,QAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AACrD,QAAA,KAAA,CAAM,IAAA,CAAK,MAAM,GAAG,CAAA,EAAA,EAAK,KAAK,SAAA,CAAU,KAAK,CAAC,CAAA,CAAE,CAAA;AAAA,MAClD,CAAC,CAAA;AAAA,IACH;AACA,IAAA,IAAI,KAAK,KAAA,EAAO;AACd,MAAA,KAAA,CAAM,IAAA,CAAK,CAAA,UAAA,EAAa,IAAA,CAAK,KAAK,CAAA,CAAE,CAAA;AAAA,IACtC;AAAA,EACF,CAAC,CAAA;AAED,EAAA,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,MAAA,CAAO,EAAE,CAAC,CAAA;AACzB,EAAA,KAAA,CAAM,KAAK,EAAE,CAAA;AAEb,EAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG;AAC/B,IAAA,KAAA,CAAM,KAAK,0BAAqB,CAAA;AAAA,EAClC,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,IAAA,CAAK,CAAA,OAAA,EAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,eAAA,CAAiB,CAAA;AAAA,EACxD;AAEA,EAAA,OAAO,KAAA,CAAM,KAAK,IAAI,CAAA;AACxB;;;AC7FA,OAAA,CACG,KAAK,wBAAwB,CAAA,CAC7B,YAAY,sDAAsD,CAAA,CAClE,QAAQ,OAAO,CAAA;AAElB,OAAA,CACG,OAAA,CAAQ,KAAK,CAAA,CACb,WAAA,CAAY,sCAAsC,CAAA,CAClD,cAAA,CAAe,2BAAA,EAA6B,8BAA8B,CAAA,CAC1E,MAAA,CAAO,qBAAA,EAAuB,gBAAA,EAAkB,QAAQ,CAAA,CACxD,MAAA,CAAO,qBAAA,EAAuB,yBAAyB,CAAA,CACvD,MAAA,CAAO,iBAAA,EAAmB,yBAAA,EAA2B,yBAAyB,CAAA,CAC9E,MAAA,CAAO,OAAO,OAAA,KAAY;AACzB,EAAA,IAAI;AACF,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,iBAAA,EAAoB,OAAA,CAAQ,OAAO,CAAA,CAAE,CAAA;AACjD,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,OAAA,CAAQ,OAAO,CAAA;AAEjD,IAAA,OAAA,CAAQ,IAAI,CAAA,+BAAA,EAAkC,OAAA,CAAQ,IAAI,CAAA,EAAA,EAAK,OAAA,CAAQ,QAAQ,CAAA,CAAA,CAAG,CAAA;AAClF,IAAA,MAAM,UAAU,iBAAA,EAAkB;AAClC,IAAA,OAAA,CAAQ,UAAU,OAAA,CAAQ,OAAA;AAE1B,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,EAAI;AAC3B,IAAA,MAAM,WAAA,GAAc,MAAM,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AAE9D,IAAA,MAAM,MAAA,GAAS,cAAA;AAAA,MACb;AAAA,QACE,UAAU,OAAA,CAAQ,QAAA;AAAA,QAClB,MAAM,OAAA,CAAQ;AAAA,OAChB;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACF;AAGA,IAAA,aAAA,CAAc,QAAQ,MAAA,EAAQ,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AAC7D,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,mBAAA,EAAwB,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AAGpD,IAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,GAAO,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAG3C,IAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC7B,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,oCAAoC,GAAG,CAAA;AACrD,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CACG,OAAA,CAAQ,QAAQ,CAAA,CAChB,WAAA,CAAY,yCAAyC,CAAA,CACrD,cAAA,CAAe,gBAAA,EAAkB,wBAAwB,CAAA,CACzD,MAAA,CAAO,CAAC,OAAA,KAAY;AACnB,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,UAAA,CAAW,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC9B,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,uBAAA,EAA0B,OAAA,CAAQ,KAAK,CAAA,CAAE,CAAA;AACvD,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAEA,IAAA,MAAM,UAAA,GAAa,YAAA,CAAa,OAAA,CAAQ,KAAA,EAAO,OAAO,CAAA;AACtD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AAEpC,IAAA,OAAA,CAAQ,GAAA,CAAI,gBAAA,CAAiB,MAAM,CAAC,CAAA;AAEpC,IAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC7B,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,GAAG,CAAA;AAC1C,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CACG,OAAA,CAAQ,aAAa,CAAA,CACrB,WAAA,CAAY,mDAAmD,CAAA,CAC/D,MAAA,CAAO,iBAAA,EAAmB,yBAAA,EAA2B,qBAAqB,CAAA,CAC1E,MAAA,CAAO,OAAO,OAAA,KAAY;AACzB,EAAA,IAAI;AACF,IAAA,MAAM,EAAE,0BAAA,EAAAC,2BAAAA,EAA4B,mBAAA,EAAAC,oBAAAA,KAAwB,MAAM,OAAA,CAAA,OAAA,EAAA,CAAA,IAAA,CAAA,OAAA,kBAAA,EAAA,EAAA,qBAAA,CAAA,CAAA;AAClE,IAAA,MAAM,EAAE,kBAAA,EAAmB,GAAI,MAAM,OAAO,sBAAsB,CAAA;AAElE,IAAA,OAAA,CAAQ,IAAI,uCAAuC,CAAA;AAEnD,IAAA,MAAM,QAAA,GAAW,IAAI,kBAAA,EAAmB;AACxC,IAAA,MAAM,MAAA,GAAS,MAAMD,2BAAAA,CAA2B,QAAQ,CAAA;AAExD,IAAA,aAAA,CAAc,QAAQ,MAAA,EAAQ,IAAA,CAAK,UAAU,MAAA,EAAQ,IAAA,EAAM,CAAC,CAAC,CAAA;AAC7D,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,mBAAA,EAAwB,OAAA,CAAQ,MAAM,CAAA,CAAE,CAAA;AACpD,IAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,GAAOC,oBAAAA,CAAoB,MAAM,CAAC,CAAA;AAE9C,IAAA,IAAI,MAAA,CAAO,SAAS,CAAA,EAAG;AACrB,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AAAA,EACF,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,6CAA6C,GAAG,CAAA;AAC9D,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AACF,CAAC,CAAA;AAEH,OAAA,CAAQ,KAAA,EAAM","file":"index.js","sourcesContent":["/**\n * CIP-0103 Conformance Test Suite\n *\n * Validates that a Provider implementation conforms to CIP-0103:\n * - Interface shape (request, on, emit, removeListener)\n * - All 10 mandatory methods are handled\n * - Event subscription returns Provider for chaining\n * - Error responses use ProviderRpcError with numeric codes\n *\n * This suite can be run against:\n * - PartyLayerProvider (native path)\n * - createProviderBridge() (bridge path)\n * - Any third-party CIP-0103 Provider\n */\n\nimport type { CIP0103Provider } from '@partylayer/core';\nimport { CIP0103_MANDATORY_METHODS, CIP0103_EVENTS } from '@partylayer/core';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CIP0103TestResult {\n name: string;\n category: 'interface' | 'method' | 'event' | 'error' | 'lifecycle';\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface CIP0103ConformanceReport {\n total: number;\n passed: number;\n failed: number;\n results: CIP0103TestResult[];\n}\n\n// ─── Runner ─────────────────────────────────────────────────────────────────\n\nexport async function runCIP0103ConformanceTests(\n provider: CIP0103Provider,\n): Promise<CIP0103ConformanceReport> {\n const results: CIP0103TestResult[] = [];\n\n // ── Interface shape tests ─────────────────────────────────────────────\n\n results.push({\n name: 'Provider has request() method',\n category: 'interface',\n passed: typeof provider.request === 'function',\n });\n\n results.push({\n name: 'Provider has on() method',\n category: 'interface',\n passed: typeof provider.on === 'function',\n });\n\n results.push({\n name: 'Provider has emit() method',\n category: 'interface',\n passed: typeof provider.emit === 'function',\n });\n\n results.push({\n name: 'Provider has removeListener() method',\n category: 'interface',\n passed: typeof provider.removeListener === 'function',\n });\n\n // ── Method presence tests ─────────────────────────────────────────────\n\n for (const method of CIP0103_MANDATORY_METHODS) {\n try {\n await provider.request({ method, params: {} });\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // A valid ProviderRpcError means the method IS handled\n // (it just may not be authorized / connected yet)\n const isValidError = isNumericCodeError(err);\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: isValidError,\n error: isValidError\n ? undefined\n : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,\n details: isValidError\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n }\n }\n\n // ── Event chaining tests ──────────────────────────────────────────────\n\n const noopHandler = () => {};\n\n const onResult = provider.on('statusChanged', noopHandler);\n results.push({\n name: 'on() returns Provider for chaining',\n category: 'event',\n passed: onResult === provider,\n error:\n onResult === provider\n ? undefined\n : 'on() did not return the Provider instance',\n });\n\n const removeResult = provider.removeListener('statusChanged', noopHandler);\n results.push({\n name: 'removeListener() returns Provider for chaining',\n category: 'event',\n passed: removeResult === provider,\n error:\n removeResult === provider\n ? undefined\n : 'removeListener() did not return the Provider instance',\n });\n\n // ── Error code validation ─────────────────────────────────────────────\n\n try {\n await provider.request({ method: '__cip0103_conformance_nonexistent__' });\n results.push({\n name: 'Unsupported method returns ProviderRpcError',\n category: 'error',\n passed: false,\n error: 'Expected error for unsupported method, got success',\n });\n } catch (err: unknown) {\n const hasNumericCode = isNumericCodeError(err);\n results.push({\n name: 'Unsupported method returns error with numeric code',\n category: 'error',\n passed: hasNumericCode,\n error: hasNumericCode\n ? undefined\n : `Expected numeric code, got: ${String(err)}`,\n details: hasNumericCode\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n\n if (hasNumericCode) {\n const code = (err as { code: number }).code;\n // Should be 4200 (UNSUPPORTED_METHOD) or -32601 (METHOD_NOT_FOUND)\n const isCorrectCode = code === 4200 || code === -32601;\n results.push({\n name: 'Unsupported method uses code 4200 or -32601',\n category: 'error',\n passed: isCorrectCode,\n error: isCorrectCode\n ? undefined\n : `Expected code 4200 or -32601, got ${code}`,\n details: { code },\n });\n }\n }\n\n // ── emit() returns boolean ────────────────────────────────────────────\n\n const emitResult = provider.emit('__cip0103_conformance_test__');\n results.push({\n name: 'emit() returns boolean',\n category: 'interface',\n passed: typeof emitResult === 'boolean',\n error:\n typeof emitResult === 'boolean'\n ? undefined\n : `emit() returned ${typeof emitResult}`,\n });\n\n // ── Transaction lifecycle tests ─────────────────────────────────────\n\n {\n const txEvents: unknown[] = [];\n const txHandler = (...args: unknown[]) => txEvents.push(...args);\n provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);\n\n try {\n await provider.request({\n method: 'prepareExecute',\n params: { tx: { _conformance: true } },\n });\n\n // Check that 'pending' was emitted\n results.push({\n name: 'prepareExecute emits txChanged with \"pending\"',\n category: 'lifecycle',\n passed: txEvents.some(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'pending',\n ),\n error: txEvents.length === 0 ? 'No txChanged events emitted' : undefined,\n });\n\n // Check that 'signed' was emitted\n const signedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'signed',\n ) as Record<string, unknown> | undefined;\n results.push({\n name: 'prepareExecute emits txChanged with \"signed\"',\n category: 'lifecycle',\n passed: !!signedEvent,\n });\n\n // Validate 'signed' payload shape\n if (signedEvent) {\n const payload = signedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'signed event has payload.signature (string)',\n category: 'lifecycle',\n passed: typeof payload?.signature === 'string',\n });\n results.push({\n name: 'signed event has payload.signedBy (string)',\n category: 'lifecycle',\n passed: typeof payload?.signedBy === 'string',\n });\n results.push({\n name: 'signed event has payload.party (string)',\n category: 'lifecycle',\n passed: typeof payload?.party === 'string',\n });\n }\n\n // Check that a terminal state was reached\n const hasTerminal = txEvents.some(\n (e) =>\n typeof e === 'object' &&\n e !== null &&\n ((e as Record<string, unknown>).status === 'executed' ||\n (e as Record<string, unknown>).status === 'failed'),\n );\n results.push({\n name: 'prepareExecute reaches terminal tx state (executed or failed)',\n category: 'lifecycle',\n passed: hasTerminal,\n });\n\n // Validate 'executed' payload shape\n const executedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'executed',\n ) as Record<string, unknown> | undefined;\n if (executedEvent) {\n const payload = executedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'executed event has payload.updateId (string)',\n category: 'lifecycle',\n passed: typeof payload?.updateId === 'string',\n });\n results.push({\n name: 'executed event has payload.completionOffset (number)',\n category: 'lifecycle',\n passed: typeof payload?.completionOffset === 'number',\n });\n }\n } catch {\n // prepareExecute may throw — still check if events were emitted\n results.push({\n name: 'prepareExecute emits txChanged events (despite error)',\n category: 'lifecycle',\n passed: txEvents.length > 0,\n error: txEvents.length === 0 ? 'No txChanged events emitted before error' : undefined,\n });\n } finally {\n provider.removeListener(CIP0103_EVENTS.TX_CHANGED, txHandler);\n }\n }\n\n // ── ledgerApi handling test ────────────────────────────────────────\n\n try {\n await provider.request({\n method: 'ledgerApi',\n params: { requestMethod: 'GET', resource: '/v1/state/acs' },\n });\n results.push({\n name: 'ledgerApi returns result (supported)',\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // ProviderRpcError with numeric code = method is recognized\n const isHandled = isNumericCodeError(err);\n results.push({\n name: 'ledgerApi is handled (returns result or ProviderRpcError)',\n category: 'method',\n passed: isHandled,\n error: isHandled ? undefined : `Unexpected error type: ${String(err)}`,\n });\n }\n\n // ── Summary ───────────────────────────────────────────────────────────\n\n const passed = results.filter((r) => r.passed).length;\n return {\n total: results.length,\n passed,\n failed: results.length - passed,\n results,\n };\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction isNumericCodeError(err: unknown): boolean {\n if (typeof err !== 'object' || err === null) return false;\n return typeof (err as Record<string, unknown>).code === 'number';\n}\n\n// ─── Formatting ─────────────────────────────────────────────────────────────\n\nexport function formatCIP0103Report(report: CIP0103ConformanceReport): string {\n const lines: string[] = [\n '═══ CIP-0103 Conformance Report ═══',\n '',\n `Total: ${report.total} Passed: ${report.passed} Failed: ${report.failed}`,\n '',\n ];\n\n const categories = ['interface', 'method', 'event', 'error', 'lifecycle'] as const;\n for (const cat of categories) {\n const catResults = report.results.filter((r) => r.category === cat);\n if (catResults.length === 0) continue;\n lines.push(`── ${cat.toUpperCase()} ──`);\n for (const r of catResults) {\n const icon = r.passed ? '✓' : '✗';\n lines.push(` ${icon} ${r.name}`);\n if (r.error) {\n lines.push(` → ${r.error}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Adapter Module Loader\n * \n * Dynamically loads adapter modules (ESM/CJS safe)\n */\n\nimport { createRequire } from 'module';\nimport { resolve } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport type { WalletAdapter } from '@partylayer/core';\n\n// This package builds to ESM (type: module), where the `require` global is\n// undefined — a bare `require(...)`/`require.resolve(...)` throws at runtime\n// (and would hit esbuild's `__require` shim in bundled consumers). Use a real\n// Node require created from this module's URL instead.\nconst nodeRequire = createRequire(import.meta.url);\n\n/**\n * Load adapter from package or path\n */\nexport async function loadAdapter(\n packageNameOrPath: string\n): Promise<WalletAdapter> {\n let adapterPath: string;\n\n // Check if it's a path\n if (packageNameOrPath.startsWith('.') || packageNameOrPath.startsWith('/')) {\n adapterPath = resolve(packageNameOrPath);\n } else {\n // Try to resolve as package\n try {\n adapterPath = nodeRequire.resolve(packageNameOrPath);\n } catch {\n throw new Error(`Cannot resolve adapter: ${packageNameOrPath}`);\n }\n }\n\n // Try to load as ESM first\n try {\n const moduleUrl = pathToFileURL(adapterPath).href;\n const module = await import(moduleUrl);\n \n // Look for default export or named export\n const adapter = module.default || module[Object.keys(module)[0]];\n \n if (!adapter) {\n throw new Error('No adapter export found');\n }\n\n // If it's a class, instantiate it\n if (typeof adapter === 'function') {\n return new adapter();\n }\n\n return adapter as WalletAdapter;\n } catch (err) {\n // Fallback to CJS\n try {\n const module = nodeRequire(adapterPath);\n const adapter = module.default || module[Object.keys(module)[0]];\n \n if (!adapter) {\n throw new Error('No adapter export found');\n }\n\n if (typeof adapter === 'function') {\n return new adapter();\n }\n\n return adapter as WalletAdapter;\n } catch (cjsErr) {\n throw new Error(\n `Failed to load adapter: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n}\n","/**\n * Adapter Conformance Tests\n * \n * Standard contract tests that all adapters must pass.\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n CapabilityKey,\n Session,\n} from '@partylayer/core';\nimport {\n CapabilityNotSupportedError,\n} from '@partylayer/core';\n\n/**\n * Test result\n */\nexport interface TestResult {\n name: string;\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Conformance test suite\n */\nexport interface ConformanceSuite {\n adapter: WalletAdapter;\n context: AdapterContext;\n results: TestResult[];\n}\n\n/**\n * Create mock adapter context\n */\nexport function createMockContext(): AdapterContext {\n return {\n appName: 'Conformance Test',\n origin: 'https://test.example.com',\n network: 'devnet',\n logger: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n telemetry: undefined,\n registry: {\n getWallet: async () => ({}),\n },\n crypto: {\n encrypt: async (data: string) => data,\n decrypt: async (data: string) => data,\n generateKey: async () => 'test-key',\n },\n storage: {\n get: async () => null,\n set: async () => {},\n remove: async () => {},\n clear: async () => {},\n },\n timeout: async (ms: number) => {\n await new Promise((resolve) => setTimeout(resolve, ms));\n throw new Error('Timeout');\n },\n };\n}\n\n/**\n * Run conformance tests\n */\nexport async function runConformanceTests(\n adapter: WalletAdapter,\n context: AdapterContext\n): Promise<TestResult[]> {\n const results: TestResult[] = [];\n\n // Test 1: Adapter has required properties\n results.push({\n name: 'Adapter has walletId',\n passed: typeof adapter.walletId === 'string' && adapter.walletId.length > 0,\n details: { walletId: adapter.walletId },\n });\n\n results.push({\n name: 'Adapter has name',\n passed: typeof adapter.name === 'string' && adapter.name.length > 0,\n details: { name: adapter.name },\n });\n\n // Test 2: getCapabilities returns valid array\n let capabilities: CapabilityKey[];\n try {\n capabilities = adapter.getCapabilities();\n results.push({\n name: 'getCapabilities returns array',\n passed: Array.isArray(capabilities),\n details: { capabilities },\n });\n\n // Check for required capabilities\n const hasConnect = capabilities.includes('connect');\n results.push({\n name: 'Capabilities include \"connect\"',\n passed: hasConnect,\n details: { capabilities },\n });\n } catch (err) {\n results.push({\n name: 'getCapabilities throws error',\n passed: false,\n error: err instanceof Error ? err.message : String(err),\n });\n return results; // Can't continue without capabilities\n }\n\n // Test 3: detectInstalled returns valid result\n try {\n const detect = await adapter.detectInstalled();\n results.push({\n name: 'detectInstalled returns valid result',\n passed:\n typeof detect === 'object' &&\n typeof detect.installed === 'boolean' &&\n (detect.installed || typeof detect.reason === 'string'),\n details: { detect },\n });\n } catch (err) {\n results.push({\n name: 'detectInstalled throws error',\n passed: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n // Test 4: If detectInstalled returns false, connect should throw WalletNotInstalledError\n // (This test requires mocking detectInstalled - skip for now or use mock adapter)\n\n // Test 5: Capability checks\n if (capabilities.includes('signMessage')) {\n if (typeof adapter.signMessage !== 'function') {\n results.push({\n name: 'signMessage capability declared but method missing',\n passed: false,\n error: 'signMessage capability declared but method not implemented',\n });\n }\n } else {\n // If signMessage not in capabilities, calling it should throw CapabilityNotSupportedError\n if (typeof adapter.signMessage === 'function') {\n try {\n await adapter.signMessage(context, {} as unknown as Session, { message: 'test' });\n results.push({\n name: 'signMessage throws CapabilityNotSupportedError when not supported',\n passed: false,\n error: 'signMessage did not throw error',\n });\n } catch (err) {\n const passed = err instanceof CapabilityNotSupportedError;\n results.push({\n name: 'signMessage throws CapabilityNotSupportedError when not supported',\n passed,\n error: passed ? undefined : err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n // Similar tests for signTransaction and submitTransaction\n if (capabilities.includes('signTransaction')) {\n if (typeof adapter.signTransaction !== 'function') {\n results.push({\n name: 'signTransaction capability declared but method missing',\n passed: false,\n error: 'signTransaction capability declared but method not implemented',\n });\n }\n }\n\n if (capabilities.includes('submitTransaction')) {\n if (typeof adapter.submitTransaction !== 'function') {\n results.push({\n name: 'submitTransaction capability declared but method missing',\n passed: false,\n error: 'submitTransaction capability declared but method not implemented',\n });\n }\n }\n\n // Test 5b: restore capability <-> method symmetry.\n //\n // We had a real bug where 3 of 5 adapters implemented restore() but did\n // not declare the 'restore' capability in getCapabilities(). The SDK\n // checks method presence at runtime so session persistence still worked,\n // but `wallet.capabilities.includes('restore')` returned false, which\n // misleads docs consumers and anyone programmatically inspecting caps.\n //\n // Enforce both directions:\n // - declared-but-missing: capability listed, no method → broken promise\n // - implemented-but-undeclared: method exists, capability missing →\n // silent drift that hides a feature from consumers\n {\n const hasRestoreMethod = typeof adapter.restore === 'function';\n const declaresRestore = capabilities.includes('restore');\n if (declaresRestore && !hasRestoreMethod) {\n results.push({\n name: 'restore capability declared but method missing',\n passed: false,\n error: `${adapter.name}: declares 'restore' capability but does not implement restore()`,\n });\n } else if (hasRestoreMethod && !declaresRestore) {\n results.push({\n name: 'restore method implemented but capability not declared',\n passed: false,\n error:\n `${adapter.name}: implements restore() but getCapabilities() does not include 'restore'. ` +\n `Add 'restore' to the returned array so consumers can discover the feature.`,\n });\n } else {\n results.push({\n name: 'restore capability / method symmetry',\n passed: true,\n details: { hasRestoreMethod, declaresRestore },\n });\n }\n }\n\n // Test 6: Error mapping\n // Verify adapter uses mapUnknownErrorToPartyLayerError\n // (This is a code inspection test - hard to test at runtime)\n\n return results;\n}\n\n/**\n * Network-truthfulness contract.\n *\n * An adapter's `connect()` MUST surface the wallet's EFFECTIVE network in\n * `session.network` (so the SDK can detect a wallet/dApp network mismatch) —\n * not merely echo the requested `context.network`.\n *\n * Drive it with a context whose `.network` differs from the network the wallet\n * actually reports (`walletReportedNetwork`); a compliant adapter returns\n * `session.network === walletReportedNetwork`. An adapter that echoes\n * `context.network` fails the contract.\n *\n * Adapters that genuinely cannot read the wallet's network must NOT claim to\n * (leave `session.network = context.network`) and must be recorded as\n * \"network-reported: no\" in the support matrix — they are out of scope for this\n * contract rather than silently passing it.\n */\nexport async function checkNetworkTruthfulness(\n adapter: WalletAdapter,\n context: AdapterContext,\n walletReportedNetwork: string,\n): Promise<TestResult> {\n const name = 'connect() session.network is the wallet effective network';\n try {\n const result = await adapter.connect(context);\n const got = result.session.network;\n const passed = got === walletReportedNetwork;\n return {\n name,\n passed,\n error: passed\n ? undefined\n : `expected session.network='${walletReportedNetwork}' (wallet-reported), got '${String(got)}'` +\n (got === context.network ? ' — merely echoed context.network' : ''),\n details: { expected: walletReportedNetwork, got, ctxNetwork: context.network },\n };\n } catch (err) {\n return { name, passed: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n","/**\n * Conformance Report Generation\n */\n\nimport type { TestResult } from './tests';\n\n/**\n * Conformance report\n */\nexport interface ConformanceReport {\n adapter: {\n walletId: string;\n name: string;\n version?: string;\n };\n environment: {\n nodeVersion: string;\n platform: string;\n timestamp: string;\n };\n results: {\n total: number;\n passed: number;\n failed: number;\n duration: number;\n };\n tests: TestResult[];\n}\n\n/**\n * Generate conformance report\n */\nexport function generateReport(\n adapter: { walletId: string; name: string; version?: string },\n tests: TestResult[],\n startTime: number\n): ConformanceReport {\n const passed = tests.filter((t) => t.passed).length;\n const failed = tests.filter((t) => !t.passed).length;\n\n return {\n adapter,\n environment: {\n nodeVersion: process.version,\n platform: process.platform,\n timestamp: new Date().toISOString(),\n },\n results: {\n total: tests.length,\n passed,\n failed,\n duration: Date.now() - startTime,\n },\n tests,\n };\n}\n\n/**\n * Format report as human-readable text\n */\nexport function formatReportText(report: ConformanceReport): string {\n const lines: string[] = [];\n\n lines.push('='.repeat(60));\n lines.push('PartyLayer Adapter Conformance Report');\n lines.push('='.repeat(60));\n lines.push('');\n lines.push(`Adapter: ${report.adapter.name} (${report.adapter.walletId})`);\n if (report.adapter.version) {\n lines.push(`Version: ${report.adapter.version}`);\n }\n lines.push(`Environment: Node ${report.environment.nodeVersion} on ${report.environment.platform}`);\n lines.push(`Timestamp: ${report.environment.timestamp}`);\n lines.push('');\n lines.push('Summary:');\n lines.push(` Total Tests: ${report.results.total}`);\n lines.push(` Passed: ${report.results.passed}`);\n lines.push(` Failed: ${report.results.failed}`);\n lines.push(` Duration: ${report.results.duration}ms`);\n lines.push('');\n lines.push('Test Results:');\n lines.push('-'.repeat(60));\n\n report.tests.forEach((test, index) => {\n const status = test.passed ? '✓' : '✗';\n lines.push(`${index + 1}. ${status} ${test.name}`);\n if (test.details) {\n Object.entries(test.details).forEach(([key, value]) => {\n lines.push(` ${key}: ${JSON.stringify(value)}`);\n });\n }\n if (test.error) {\n lines.push(` Error: ${test.error}`);\n }\n });\n\n lines.push('-'.repeat(60));\n lines.push('');\n\n if (report.results.failed === 0) {\n lines.push('✓ All tests passed!');\n } else {\n lines.push(`✗ ${report.results.failed} test(s) failed`);\n }\n\n return lines.join('\\n');\n}\n","#!/usr/bin/env node\n/**\n * PartyLayer Conformance Runner CLI\n * \n * Runs adapter conformance tests and generates reports.\n */\n\nimport { program } from 'commander';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { loadAdapter } from './loader';\nimport { runConformanceTests, createMockContext } from './tests';\nimport { generateReport, formatReportText, type ConformanceReport } from './report';\n\nprogram\n .name('partylayer-conformance')\n .description('Run conformance tests for PartyLayer wallet adapters')\n .version('0.1.0');\n\nprogram\n .command('run')\n .description('Run conformance tests for an adapter')\n .requiredOption('--adapter <packageOrPath>', 'Adapter package name or path')\n .option('--network <network>', 'Network to use', 'devnet')\n .option('--registryUrl <url>', 'Registry URL (optional)')\n .option('--output <path>', 'Output JSON report path', 'conformance-report.json')\n .action(async (options) => {\n try {\n console.log(`Loading adapter: ${options.adapter}`);\n const adapter = await loadAdapter(options.adapter);\n\n console.log(`Running conformance tests for: ${adapter.name} (${adapter.walletId})`);\n const context = createMockContext();\n context.network = options.network as 'devnet' | 'testnet' | 'mainnet';\n\n const startTime = Date.now();\n const testResults = await runConformanceTests(adapter, context);\n\n const report = generateReport(\n {\n walletId: adapter.walletId,\n name: adapter.name,\n },\n testResults,\n startTime\n );\n\n // Write JSON report\n writeFileSync(options.output, JSON.stringify(report, null, 2));\n console.log(`\\nReport written to: ${options.output}`);\n\n // Print human-readable summary\n console.log('\\n' + formatReportText(report));\n\n // Exit with error code if tests failed\n if (report.results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error running conformance tests:', err);\n process.exit(1);\n }\n });\n\nprogram\n .command('report')\n .description('Format and display a conformance report')\n .requiredOption('--input <path>', 'Input JSON report path')\n .action((options) => {\n try {\n if (!existsSync(options.input)) {\n console.error(`Report file not found: ${options.input}`);\n process.exit(1);\n }\n\n const reportJson = readFileSync(options.input, 'utf-8');\n const report = JSON.parse(reportJson) as ConformanceReport;\n\n console.log(formatReportText(report));\n\n if (report.results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error reading report:', err);\n process.exit(1);\n }\n });\n\nprogram\n .command('run-cip0103')\n .description('Run CIP-0103 conformance tests against a Provider')\n .option('--output <path>', 'Output JSON report path', 'cip0103-report.json')\n .action(async (options) => {\n try {\n const { runCIP0103ConformanceTests, formatCIP0103Report } = await import('./cip0103-tests');\n const { PartyLayerProvider } = await import('@partylayer/provider');\n\n console.log('Running CIP-0103 conformance tests...');\n\n const provider = new PartyLayerProvider();\n const report = await runCIP0103ConformanceTests(provider);\n\n writeFileSync(options.output, JSON.stringify(report, null, 2));\n console.log(`\\nReport written to: ${options.output}`);\n console.log('\\n' + formatCIP0103Report(report));\n\n if (report.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error running CIP-0103 conformance tests:', err);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
1
+ {"version":3,"sources":["../src/cip0103-tests.ts","../src/loader.ts","../src/tests.ts","../src/report.ts","../src/index.ts"],"names":["resolve","runCIP0103ConformanceTests","formatCIP0103Report"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * CIP-0103 Conformance Test Suite\n *\n * Validates that a Provider implementation conforms to CIP-0103:\n * - Interface shape (request, on, emit, removeListener)\n * - All 10 mandatory methods are handled\n *\n * \"Mandatory\" means the specification's synchronous method table, and nothing\n * else. It iterates CIP0103_MANDATORY_METHODS, which is written out explicitly\n * rather than derived from CIP0103_METHODS: this SDK speaks one method the\n * standard does not define (prepareExecuteAndWait, from the upstream client),\n * and that method is DELIBERATELY EXCLUDED here. A vendor running this suite\n * reads its output as a list of their obligations, so an extension of ours\n * appearing in it would tell them the standard requires something it does not.\n * See the comment on CIP0103_MANDATORY_METHODS in @partylayer/core.\n * - Event subscription returns Provider for chaining\n * - Error responses use ProviderRpcError with numeric codes\n *\n * This suite can be run against:\n * - PartyLayerProvider (native path)\n * - createProviderBridge() (bridge path)\n * - Any third-party CIP-0103 Provider\n */\n\nimport type { CIP0103Provider } from '@partylayer/core';\nimport { CIP0103_MANDATORY_METHODS, CIP0103_EVENTS } from '@partylayer/core';\n\n// ─── Types ──────────────────────────────────────────────────────────────────\n\nexport interface CIP0103TestResult {\n name: string;\n category: 'interface' | 'method' | 'event' | 'error' | 'lifecycle';\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\nexport interface CIP0103ConformanceReport {\n total: number;\n passed: number;\n failed: number;\n results: CIP0103TestResult[];\n}\n\n// ─── Runner ─────────────────────────────────────────────────────────────────\n\nexport async function runCIP0103ConformanceTests(\n provider: CIP0103Provider,\n): Promise<CIP0103ConformanceReport> {\n const results: CIP0103TestResult[] = [];\n\n // ── Interface shape tests ─────────────────────────────────────────────\n\n results.push({\n name: 'Provider has request() method',\n category: 'interface',\n passed: typeof provider.request === 'function',\n });\n\n results.push({\n name: 'Provider has on() method',\n category: 'interface',\n passed: typeof provider.on === 'function',\n });\n\n results.push({\n name: 'Provider has emit() method',\n category: 'interface',\n passed: typeof provider.emit === 'function',\n });\n\n results.push({\n name: 'Provider has removeListener() method',\n category: 'interface',\n passed: typeof provider.removeListener === 'function',\n });\n\n // ── Method presence tests ─────────────────────────────────────────────\n\n for (const method of CIP0103_MANDATORY_METHODS) {\n try {\n await provider.request({ method, params: {} });\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // A valid ProviderRpcError means the method IS handled\n // (it just may not be authorized / connected yet)\n const isValidError = isNumericCodeError(err);\n const unsupported = isValidError && (err.code === 4200 || err.code === -32601);\n results.push({\n name: `Method \"${method}\" is handled`,\n category: 'method',\n passed: isValidError && !unsupported,\n error: unsupported ? 'A mandatory method cannot be unsupported' : isValidError\n ? undefined\n : `Expected ProviderRpcError with numeric code, got: ${String(err)}`,\n details: isValidError\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n }\n }\n\n // ── Event chaining tests ──────────────────────────────────────────────\n\n const noopHandler = () => {};\n\n const onResult = provider.on('statusChanged', noopHandler);\n results.push({\n name: 'on() returns Provider for chaining',\n category: 'event',\n passed: onResult === provider,\n error:\n onResult === provider\n ? undefined\n : 'on() did not return the Provider instance',\n });\n\n const removeResult = provider.removeListener('statusChanged', noopHandler);\n results.push({\n name: 'removeListener() returns Provider for chaining',\n category: 'event',\n passed: removeResult === provider,\n error:\n removeResult === provider\n ? undefined\n : 'removeListener() did not return the Provider instance',\n });\n\n // ── Error code validation ─────────────────────────────────────────────\n\n try {\n await provider.request({ method: '__cip0103_conformance_nonexistent__' });\n results.push({\n name: 'Unsupported method returns ProviderRpcError',\n category: 'error',\n passed: false,\n error: 'Expected error for unsupported method, got success',\n });\n } catch (err: unknown) {\n const hasNumericCode = isNumericCodeError(err);\n results.push({\n name: 'Unsupported method returns error with numeric code',\n category: 'error',\n passed: hasNumericCode,\n error: hasNumericCode\n ? undefined\n : `Expected numeric code, got: ${String(err)}`,\n details: hasNumericCode\n ? { code: (err as { code: number }).code }\n : undefined,\n });\n\n if (hasNumericCode) {\n const code = (err as { code: number }).code;\n // Should be 4200 (UNSUPPORTED_METHOD) or -32601 (METHOD_NOT_FOUND)\n const isCorrectCode = code === 4200 || code === -32601;\n results.push({\n name: 'Unsupported method uses code 4200 or -32601',\n category: 'error',\n passed: isCorrectCode,\n error: isCorrectCode\n ? undefined\n : `Expected code 4200 or -32601, got ${code}`,\n details: { code },\n });\n }\n }\n\n // ── emit() returns boolean ────────────────────────────────────────────\n\n const emitResult = provider.emit('__cip0103_conformance_test__');\n results.push({\n name: 'emit() returns boolean',\n category: 'interface',\n passed: typeof emitResult === 'boolean',\n error:\n typeof emitResult === 'boolean'\n ? undefined\n : `emit() returned ${typeof emitResult}`,\n });\n\n // ── Transaction lifecycle tests ─────────────────────────────────────\n\n {\n const txEvents: unknown[] = [];\n const txHandler = (...args: unknown[]) => txEvents.push(...args);\n provider.on(CIP0103_EVENTS.TX_CHANGED, txHandler);\n\n try {\n // Method-presence checks include disconnect. Establish authorization again\n // before exercising a write; a disconnected provider must not manufacture\n // transaction events merely to make this suite pass.\n const connected = await provider.request<{ isConnected: boolean }>({ method: 'connect' });\n if (connected?.isConnected !== true) throw new Error('Wallet connection is required for lifecycle checks');\n await provider.request({\n method: 'prepareExecute',\n params: { tx: { _conformance: true } },\n });\n\n // Check that 'pending' was emitted\n results.push({\n name: 'prepareExecute emits txChanged with \"pending\"',\n category: 'lifecycle',\n passed: txEvents.some(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'pending',\n ),\n error: txEvents.length === 0 ? 'No txChanged events emitted' : undefined,\n });\n\n // Check that 'signed' was emitted\n const signedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'signed',\n ) as Record<string, unknown> | undefined;\n results.push({\n name: 'prepareExecute emits txChanged with \"signed\"',\n category: 'lifecycle',\n passed: !!signedEvent,\n });\n\n // Validate 'signed' payload shape\n if (signedEvent) {\n const payload = signedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'signed event has payload.signature (string)',\n category: 'lifecycle',\n passed: typeof payload?.signature === 'string',\n });\n results.push({\n name: 'signed event has payload.signedBy (string)',\n category: 'lifecycle',\n passed: typeof payload?.signedBy === 'string',\n });\n results.push({\n name: 'signed event has payload.party (string)',\n category: 'lifecycle',\n passed: typeof payload?.party === 'string',\n });\n }\n\n // Check that a terminal state was reached\n const hasTerminal = txEvents.some(\n (e) =>\n typeof e === 'object' &&\n e !== null &&\n ((e as Record<string, unknown>).status === 'executed' ||\n (e as Record<string, unknown>).status === 'failed'),\n );\n results.push({\n name: 'prepareExecute reaches terminal tx state (executed or failed)',\n category: 'lifecycle',\n passed: hasTerminal,\n });\n\n // Validate 'executed' payload shape\n const executedEvent = txEvents.find(\n (e) => typeof e === 'object' && e !== null && (e as Record<string, unknown>).status === 'executed',\n ) as Record<string, unknown> | undefined;\n if (executedEvent) {\n const payload = executedEvent.payload as Record<string, unknown> | undefined;\n results.push({\n name: 'executed event has payload.updateId (string)',\n category: 'lifecycle',\n passed: typeof payload?.updateId === 'string',\n });\n results.push({\n name: 'executed event has payload.completionOffset (number)',\n category: 'lifecycle',\n passed: typeof payload?.completionOffset === 'number',\n });\n }\n } catch {\n // prepareExecute may throw — still check if events were emitted\n results.push({\n name: 'prepareExecute emits txChanged events (despite error)',\n category: 'lifecycle',\n passed: txEvents.length > 0,\n error: txEvents.length === 0 ? 'No txChanged events emitted before error' : undefined,\n });\n } finally {\n provider.removeListener(CIP0103_EVENTS.TX_CHANGED, txHandler);\n }\n }\n\n // ── ledgerApi handling test ────────────────────────────────────────\n\n try {\n await provider.request({\n method: 'ledgerApi',\n params: { requestMethod: 'GET', resource: '/v1/state/acs' },\n });\n results.push({\n name: 'ledgerApi returns result (supported)',\n category: 'method',\n passed: true,\n });\n } catch (err: unknown) {\n // ProviderRpcError with numeric code = method is recognized\n const isHandled = isNumericCodeError(err) && err.code !== 4200 && err.code !== -32601;\n results.push({\n name: 'ledgerApi is handled (returns result or ProviderRpcError)',\n category: 'method',\n passed: isHandled,\n error: isHandled ? undefined : `Unexpected error type: ${String(err)}`,\n });\n }\n\n // ── Summary ───────────────────────────────────────────────────────────\n\n const passed = results.filter((r) => r.passed).length;\n return {\n total: results.length,\n passed,\n failed: results.length - passed,\n results,\n };\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────\n\nfunction isNumericCodeError(err: unknown): err is { code: number } {\n if (typeof err !== 'object' || err === null) return false;\n return typeof (err as Record<string, unknown>).code === 'number';\n}\n\n// ─── Formatting ─────────────────────────────────────────────────────────────\n\nexport function formatCIP0103Report(report: CIP0103ConformanceReport): string {\n const lines: string[] = [\n '═══ CIP-0103 Conformance Report ═══',\n '',\n `Total: ${report.total} Passed: ${report.passed} Failed: ${report.failed}`,\n '',\n ];\n\n const categories = ['interface', 'method', 'event', 'error', 'lifecycle'] as const;\n for (const cat of categories) {\n const catResults = report.results.filter((r) => r.category === cat);\n if (catResults.length === 0) continue;\n lines.push(`── ${cat.toUpperCase()} ──`);\n for (const r of catResults) {\n const icon = r.passed ? '✓' : '✗';\n lines.push(` ${icon} ${r.name}`);\n if (r.error) {\n lines.push(` → ${r.error}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n","/**\n * Adapter Module Loader\n * \n * Dynamically loads adapter modules (ESM/CJS safe)\n */\n\nimport { createRequire } from 'module';\nimport { resolve } from 'path';\nimport { pathToFileURL } from 'url';\n\nimport type { WalletAdapter } from '@partylayer/core';\n\n// This package builds to ESM (type: module), where the `require` global is\n// undefined — a bare `require(...)`/`require.resolve(...)` throws at runtime\n// (and would hit esbuild's `__require` shim in bundled consumers). Use a real\n// Node require created from this module's URL instead.\nconst nodeRequire = createRequire(import.meta.url);\n\n/**\n * Load adapter from package or path\n */\nexport async function loadAdapter(\n packageNameOrPath: string\n): Promise<WalletAdapter> {\n let adapterPath: string;\n\n // Check if it's a path\n if (packageNameOrPath.startsWith('.') || packageNameOrPath.startsWith('/')) {\n adapterPath = resolve(packageNameOrPath);\n } else {\n // Try to resolve as package\n try {\n adapterPath = nodeRequire.resolve(packageNameOrPath);\n } catch {\n throw new Error(`Cannot resolve adapter: ${packageNameOrPath}`);\n }\n }\n\n // Try to load as ESM first\n try {\n const moduleUrl = pathToFileURL(adapterPath).href;\n const module = await import(moduleUrl);\n \n // Look for default export or named export\n const adapter = module.default || module[Object.keys(module)[0]];\n \n if (!adapter) {\n throw new Error('No adapter export found');\n }\n\n // If it's a class, instantiate it\n if (typeof adapter === 'function') {\n return new adapter();\n }\n\n return adapter as WalletAdapter;\n } catch (err) {\n // Fallback to CJS\n try {\n const module = nodeRequire(adapterPath);\n const adapter = module.default || module[Object.keys(module)[0]];\n \n if (!adapter) {\n throw new Error('No adapter export found');\n }\n\n if (typeof adapter === 'function') {\n return new adapter();\n }\n\n return adapter as WalletAdapter;\n } catch (cjsErr) {\n throw new Error(\n `Failed to load adapter: ${err instanceof Error ? err.message : String(err)}`\n );\n }\n }\n}\n","/**\n * Adapter Conformance Tests\n * \n * Standard contract tests that all adapters must pass.\n */\n\nimport type {\n WalletAdapter,\n AdapterContext,\n CapabilityKey,\n Session,\n} from '@partylayer/core';\nimport {\n CapabilityNotSupportedError,\n} from '@partylayer/core';\n\n/**\n * Test result\n */\nexport interface TestResult {\n name: string;\n passed: boolean;\n error?: string;\n details?: Record<string, unknown>;\n}\n\n/**\n * Conformance test suite\n */\nexport interface ConformanceSuite {\n adapter: WalletAdapter;\n context: AdapterContext;\n results: TestResult[];\n}\n\n/**\n * Create mock adapter context\n */\nexport function createMockContext(): AdapterContext {\n return {\n appName: 'Conformance Test',\n origin: 'https://test.example.com',\n network: 'devnet',\n logger: {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n },\n telemetry: undefined,\n registry: {\n getWallet: async () => ({}),\n },\n crypto: {\n encrypt: async (data: string) => data,\n decrypt: async (data: string) => data,\n generateKey: async () => 'test-key',\n },\n storage: {\n get: async () => null,\n set: async () => {},\n remove: async () => {},\n clear: async () => {},\n },\n timeout: async (ms: number) => {\n await new Promise((resolve) => setTimeout(resolve, ms));\n throw new Error('Timeout');\n },\n };\n}\n\n/**\n * Run conformance tests\n */\nexport async function runConformanceTests(\n adapter: WalletAdapter,\n context: AdapterContext\n): Promise<TestResult[]> {\n const results: TestResult[] = [];\n\n // Test 1: Adapter has required properties\n results.push({\n name: 'Adapter has walletId',\n passed: typeof adapter.walletId === 'string' && adapter.walletId.length > 0,\n details: { walletId: adapter.walletId },\n });\n\n results.push({\n name: 'Adapter has name',\n passed: typeof adapter.name === 'string' && adapter.name.length > 0,\n details: { name: adapter.name },\n });\n\n // Test 2: getCapabilities returns valid array\n let capabilities: CapabilityKey[];\n try {\n capabilities = adapter.getCapabilities();\n results.push({\n name: 'getCapabilities returns array',\n passed: Array.isArray(capabilities),\n details: { capabilities },\n });\n\n // Check for required capabilities\n const hasConnect = capabilities.includes('connect');\n results.push({\n name: 'Capabilities include \"connect\"',\n passed: hasConnect,\n details: { capabilities },\n });\n } catch (err) {\n results.push({\n name: 'getCapabilities throws error',\n passed: false,\n error: err instanceof Error ? err.message : String(err),\n });\n return results; // Can't continue without capabilities\n }\n\n // Test 3: detectInstalled returns valid result\n try {\n const detect = await adapter.detectInstalled();\n results.push({\n name: 'detectInstalled returns valid result',\n passed:\n typeof detect === 'object' &&\n typeof detect.installed === 'boolean' &&\n (detect.installed || typeof detect.reason === 'string'),\n details: { detect },\n });\n } catch (err) {\n results.push({\n name: 'detectInstalled throws error',\n passed: false,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n\n // Test 4: If detectInstalled returns false, connect should throw WalletNotInstalledError\n // (This test requires mocking detectInstalled - skip for now or use mock adapter)\n\n // Test 5: Capability checks\n if (capabilities.includes('signMessage')) {\n if (typeof adapter.signMessage !== 'function') {\n results.push({\n name: 'signMessage capability declared but method missing',\n passed: false,\n error: 'signMessage capability declared but method not implemented',\n });\n }\n } else {\n // If signMessage not in capabilities, calling it should throw CapabilityNotSupportedError\n if (typeof adapter.signMessage === 'function') {\n try {\n await adapter.signMessage(context, {} as unknown as Session, { message: 'test' });\n results.push({\n name: 'signMessage throws CapabilityNotSupportedError when not supported',\n passed: false,\n error: 'signMessage did not throw error',\n });\n } catch (err) {\n const passed = err instanceof CapabilityNotSupportedError;\n results.push({\n name: 'signMessage throws CapabilityNotSupportedError when not supported',\n passed,\n error: passed ? undefined : err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n // Similar tests for signTransaction and submitTransaction\n if (capabilities.includes('signTransaction')) {\n if (typeof adapter.signTransaction !== 'function') {\n results.push({\n name: 'signTransaction capability declared but method missing',\n passed: false,\n error: 'signTransaction capability declared but method not implemented',\n });\n }\n }\n\n if (capabilities.includes('submitTransaction')) {\n if (typeof adapter.submitTransaction !== 'function') {\n results.push({\n name: 'submitTransaction capability declared but method missing',\n passed: false,\n error: 'submitTransaction capability declared but method not implemented',\n });\n }\n }\n\n // Test 5b: restore capability <-> method symmetry.\n //\n // We had a real bug where 3 of 5 adapters implemented restore() but did\n // not declare the 'restore' capability in getCapabilities(). The SDK\n // checks method presence at runtime so session persistence still worked,\n // but `wallet.capabilities.includes('restore')` returned false, which\n // misleads docs consumers and anyone programmatically inspecting caps.\n //\n // Enforce both directions:\n // - declared-but-missing: capability listed, no method → broken promise\n // - implemented-but-undeclared: method exists, capability missing →\n // silent drift that hides a feature from consumers\n {\n const hasRestoreMethod = typeof adapter.restore === 'function';\n const declaresRestore = capabilities.includes('restore');\n if (declaresRestore && !hasRestoreMethod) {\n results.push({\n name: 'restore capability declared but method missing',\n passed: false,\n error: `${adapter.name}: declares 'restore' capability but does not implement restore()`,\n });\n } else if (hasRestoreMethod && !declaresRestore) {\n results.push({\n name: 'restore method implemented but capability not declared',\n passed: false,\n error:\n `${adapter.name}: implements restore() but getCapabilities() does not include 'restore'. ` +\n `Add 'restore' to the returned array so consumers can discover the feature.`,\n });\n } else {\n results.push({\n name: 'restore capability / method symmetry',\n passed: true,\n details: { hasRestoreMethod, declaresRestore },\n });\n }\n }\n\n // Test 6: Error mapping\n // Verify adapter uses mapUnknownErrorToPartyLayerError\n // (This is a code inspection test - hard to test at runtime)\n\n return results;\n}\n\n/**\n * Network-truthfulness contract.\n *\n * An adapter's `connect()` MUST surface the wallet's EFFECTIVE network in\n * `session.network` (so the SDK can detect a wallet/dApp network mismatch) —\n * not merely echo the requested `context.network`.\n *\n * Drive it with a context whose `.network` differs from the network the wallet\n * actually reports (`walletReportedNetwork`); a compliant adapter returns\n * `session.network === walletReportedNetwork`. An adapter that echoes\n * `context.network` fails the contract.\n *\n * Adapters that genuinely cannot read the wallet's network must NOT claim to\n * (leave `session.network = context.network`) and must be recorded as\n * \"network-reported: no\" in the support matrix — they are out of scope for this\n * contract rather than silently passing it.\n */\nexport async function checkNetworkTruthfulness(\n adapter: WalletAdapter,\n context: AdapterContext,\n walletReportedNetwork: string,\n): Promise<TestResult> {\n const name = 'connect() session.network is the wallet effective network';\n try {\n const result = await adapter.connect(context);\n const got = result.session.network;\n const passed = got === walletReportedNetwork;\n return {\n name,\n passed,\n error: passed\n ? undefined\n : `expected session.network='${walletReportedNetwork}' (wallet-reported), got '${String(got)}'` +\n (got === context.network ? ' — merely echoed context.network' : ''),\n details: { expected: walletReportedNetwork, got, ctxNetwork: context.network },\n };\n } catch (err) {\n return { name, passed: false, error: err instanceof Error ? err.message : String(err) };\n }\n}\n","/**\n * Conformance Report Generation\n */\n\nimport type { TestResult } from './tests';\n\n/**\n * Conformance report\n */\nexport interface ConformanceReport {\n adapter: {\n walletId: string;\n name: string;\n version?: string;\n };\n environment: {\n nodeVersion: string;\n platform: string;\n timestamp: string;\n };\n results: {\n total: number;\n passed: number;\n failed: number;\n duration: number;\n };\n tests: TestResult[];\n}\n\n/**\n * Generate conformance report\n */\nexport function generateReport(\n adapter: { walletId: string; name: string; version?: string },\n tests: TestResult[],\n startTime: number\n): ConformanceReport {\n const passed = tests.filter((t) => t.passed).length;\n const failed = tests.filter((t) => !t.passed).length;\n\n return {\n adapter,\n environment: {\n nodeVersion: process.version,\n platform: process.platform,\n timestamp: new Date().toISOString(),\n },\n results: {\n total: tests.length,\n passed,\n failed,\n duration: Date.now() - startTime,\n },\n tests,\n };\n}\n\n/**\n * Format report as human-readable text\n */\nexport function formatReportText(report: ConformanceReport): string {\n const lines: string[] = [];\n\n lines.push('='.repeat(60));\n lines.push('PartyLayer Adapter Conformance Report');\n lines.push('='.repeat(60));\n lines.push('');\n lines.push(`Adapter: ${report.adapter.name} (${report.adapter.walletId})`);\n if (report.adapter.version) {\n lines.push(`Version: ${report.adapter.version}`);\n }\n lines.push(`Environment: Node ${report.environment.nodeVersion} on ${report.environment.platform}`);\n lines.push(`Timestamp: ${report.environment.timestamp}`);\n lines.push('');\n lines.push('Summary:');\n lines.push(` Total Tests: ${report.results.total}`);\n lines.push(` Passed: ${report.results.passed}`);\n lines.push(` Failed: ${report.results.failed}`);\n lines.push(` Duration: ${report.results.duration}ms`);\n lines.push('');\n lines.push('Test Results:');\n lines.push('-'.repeat(60));\n\n report.tests.forEach((test, index) => {\n const status = test.passed ? '✓' : '✗';\n lines.push(`${index + 1}. ${status} ${test.name}`);\n if (test.details) {\n Object.entries(test.details).forEach(([key, value]) => {\n lines.push(` ${key}: ${JSON.stringify(value)}`);\n });\n }\n if (test.error) {\n lines.push(` Error: ${test.error}`);\n }\n });\n\n lines.push('-'.repeat(60));\n lines.push('');\n\n if (report.results.failed === 0) {\n lines.push('✓ All tests passed!');\n } else {\n lines.push(`✗ ${report.results.failed} test(s) failed`);\n }\n\n return lines.join('\\n');\n}\n","#!/usr/bin/env node\n/**\n * PartyLayer Conformance Runner CLI\n * \n * Runs adapter conformance tests and generates reports.\n */\n\nimport { program } from 'commander';\nimport { readFileSync, writeFileSync, existsSync } from 'fs';\nimport { loadAdapter } from './loader';\nimport { runConformanceTests, createMockContext } from './tests';\nimport { generateReport, formatReportText, type ConformanceReport } from './report';\n\nprogram\n .name('partylayer-conformance')\n .description('Run conformance tests for PartyLayer wallet adapters')\n .version('0.1.0');\n\nprogram\n .command('run')\n .description('Run conformance tests for an adapter')\n .requiredOption('--adapter <packageOrPath>', 'Adapter package name or path')\n .option('--network <network>', 'Network to use', 'devnet')\n .option('--registryUrl <url>', 'Registry URL (optional)')\n .option('--output <path>', 'Output JSON report path', 'conformance-report.json')\n .action(async (options) => {\n try {\n console.log(`Loading adapter: ${options.adapter}`);\n const adapter = await loadAdapter(options.adapter);\n\n console.log(`Running conformance tests for: ${adapter.name} (${adapter.walletId})`);\n const context = createMockContext();\n context.network = options.network as 'devnet' | 'testnet' | 'mainnet';\n\n const startTime = Date.now();\n const testResults = await runConformanceTests(adapter, context);\n\n const report = generateReport(\n {\n walletId: adapter.walletId,\n name: adapter.name,\n },\n testResults,\n startTime\n );\n\n // Write JSON report\n writeFileSync(options.output, JSON.stringify(report, null, 2));\n console.log(`\\nReport written to: ${options.output}`);\n\n // Print human-readable summary\n console.log('\\n' + formatReportText(report));\n\n // Exit with error code if tests failed\n if (report.results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error running conformance tests:', err);\n process.exit(1);\n }\n });\n\nprogram\n .command('report')\n .description('Format and display a conformance report')\n .requiredOption('--input <path>', 'Input JSON report path')\n .action((options) => {\n try {\n if (!existsSync(options.input)) {\n console.error(`Report file not found: ${options.input}`);\n process.exit(1);\n }\n\n const reportJson = readFileSync(options.input, 'utf-8');\n const report = JSON.parse(reportJson) as ConformanceReport;\n\n console.log(formatReportText(report));\n\n if (report.results.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error reading report:', err);\n process.exit(1);\n }\n });\n\nprogram\n .command('run-cip0103')\n .description('Run CIP-0103 conformance tests against a Provider')\n .option('--output <path>', 'Output JSON report path', 'cip0103-report.json')\n .action(async (options) => {\n try {\n const { runCIP0103ConformanceTests, formatCIP0103Report } = await import('./cip0103-tests');\n const { PartyLayerProvider } = await import('@partylayer/provider');\n\n console.log('Running CIP-0103 conformance tests...');\n\n const provider = new PartyLayerProvider();\n const report = await runCIP0103ConformanceTests(provider);\n\n writeFileSync(options.output, JSON.stringify(report, null, 2));\n console.log(`\\nReport written to: ${options.output}`);\n console.log('\\n' + formatCIP0103Report(report));\n\n if (report.failed > 0) {\n process.exit(1);\n }\n } catch (err) {\n console.error('Error running CIP-0103 conformance tests:', err);\n process.exit(1);\n }\n });\n\nprogram.parse();\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@partylayer/conformance-runner",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": "CLI tool for running adapter conformance tests",
5
5
  "type": "module",
6
6
  "bin": {
@@ -29,8 +29,8 @@
29
29
  "license": "MIT",
30
30
  "dependencies": {
31
31
  "commander": "^14.0.2",
32
- "@partylayer/core": "^0.14.0",
33
- "@partylayer/provider": "^0.6.0"
32
+ "@partylayer/provider": "^0.6.2",
33
+ "@partylayer/core": "^0.16.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^20.11.0",