@notabene/verify-proof 1.11.0 → 1.12.0-next.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.
- package/README.md +21 -15
- package/dist/cjs/bitcoin-UIEQV3IM.cjs +403 -0
- package/dist/cjs/bitcoin-UIEQV3IM.cjs.map +1 -0
- package/dist/cjs/cardano-QG2S452K.cjs +36 -0
- package/dist/cjs/cardano-QG2S452K.cjs.map +1 -0
- package/dist/cjs/concordium-4B33UJJ5.cjs +44 -0
- package/dist/cjs/concordium-4B33UJJ5.cjs.map +1 -0
- package/dist/cjs/cosmos-JTT3AZCF.cjs +92 -0
- package/dist/cjs/cosmos-JTT3AZCF.cjs.map +1 -0
- package/dist/cjs/eth-BVXX47HH.cjs +36 -0
- package/dist/cjs/eth-BVXX47HH.cjs.map +1 -0
- package/dist/cjs/index.cjs +68 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/cjs/index.d.cts +5 -0
- package/dist/cjs/solana-4WNBEQSU.cjs +348 -0
- package/dist/cjs/solana-4WNBEQSU.cjs.map +1 -0
- package/dist/cjs/tron-IM2O2VLM.cjs +57 -0
- package/dist/cjs/tron-IM2O2VLM.cjs.map +1 -0
- package/dist/cjs/xlm-CHT7RN4Z.cjs +27 -0
- package/dist/cjs/xlm-CHT7RN4Z.cjs.map +1 -0
- package/dist/cjs/xrpl-HJ2XWSOO.cjs +74 -0
- package/dist/cjs/xrpl-HJ2XWSOO.cjs.map +1 -0
- package/dist/esm/bitcoin-BTZ4TXEK.js +401 -0
- package/dist/esm/bitcoin-BTZ4TXEK.js.map +1 -0
- package/dist/esm/cardano-OMGAPH5N.js +30 -0
- package/dist/esm/cardano-OMGAPH5N.js.map +1 -0
- package/dist/esm/concordium-JJ5VEIOA.js +42 -0
- package/dist/esm/concordium-JJ5VEIOA.js.map +1 -0
- package/dist/esm/cosmos-AVIWAIX7.js +90 -0
- package/dist/esm/cosmos-AVIWAIX7.js.map +1 -0
- package/dist/esm/eth-GI4Z5V4T.js +33 -0
- package/dist/esm/eth-GI4Z5V4T.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +66 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/solana-ZARDAF6O.js +341 -0
- package/dist/esm/solana-ZARDAF6O.js.map +1 -0
- package/dist/esm/tron-FI2B6DRS.js +52 -0
- package/dist/esm/tron-FI2B6DRS.js.map +1 -0
- package/dist/esm/xlm-TNRZ5CFC.js +25 -0
- package/dist/esm/xlm-TNRZ5CFC.js.map +1 -0
- package/dist/esm/xrpl-52IBJ4EW.js +69 -0
- package/dist/esm/xrpl-52IBJ4EW.js.map +1 -0
- package/package.json +27 -6
- package/src/bitcoin.ts +43 -19
- package/src/cashaddr.ts +157 -0
- package/src/concordium.ts +34 -283
- package/src/cosmos.ts +44 -6
- package/src/index.ts +31 -20
- package/src/tests/bitcoin.test.ts +527 -16
- package/src/tests/concordium.test.ts +96 -134
- package/src/tests/cosmos.test.ts +139 -0
- package/src/tests/index.test.ts +7 -7
- package/src/tests/solana.test.ts +1 -1
- package/src/tests/xrpl.test.ts +8 -6
- package/dist/bitcoin.d.ts +0 -2
- package/dist/cardano.d.ts +0 -2
- package/dist/concordium.d.ts +0 -15
- package/dist/cosmos.d.ts +0 -2
- package/dist/eth.d.ts +0 -4
- package/dist/index.cjs +0 -2
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/index.modern.js +0 -2
- package/dist/index.modern.js.map +0 -1
- package/dist/index.umd.js +0 -2
- package/dist/index.umd.js.map +0 -1
- package/dist/solana.d.ts +0 -17
- package/dist/tests/bitcoin.test.d.ts +0 -1
- package/dist/tests/cardano.test.d.ts +0 -1
- package/dist/tests/concordium.test.d.ts +0 -1
- package/dist/tests/cosmos.test.d.ts +0 -1
- package/dist/tests/eth.test.d.ts +0 -1
- package/dist/tests/index.test.d.ts +0 -1
- package/dist/tests/solana.test.d.ts +0 -1
- package/dist/tests/tron.test.d.ts +0 -1
- package/dist/tests/xlm.test.d.ts +0 -1
- package/dist/tests/xrpl.test.d.ts +0 -1
- package/dist/tron.d.ts +0 -6
- package/dist/xlm.d.ts +0 -2
- package/dist/xrpl.d.ts +0 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/solana.ts"],"names":[],"mappings":";;;;;;AAmCA,eAAsB,sBACpB,KAAA,EACyB;AACzB,EAAA,MAAM,CAAC,MAAM,OAAO,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC/C,EAAA,IAAI,EAAA,KAAO,UAAU,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAEnE,EAAA,IAAI;AACF,IAAA,MAAM,SAAA,GAAY,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACvC,IAAA,MAAM,eAAe,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,MAAM,WAAW,CAAA;AAC/D,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,MAAA,CAAO,KAAA,CAAM,KAAK,CAAA;AAChD,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAA;AAAA,MAClC,YAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,OAAO;AAAA,MACL,GAAG,KAAA;AAAA,MACH,MAAA,EAAQ,QAAA,GAAW,WAAA,CAAY,QAAA,GAAW,WAAA,CAAY;AAAA,KACxD;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AACF;AAEA,SAAS,oBAAoB,GAAA,EAAgC;AAC3D,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,KAAA;AAE5C,EAAA,MAAM,KAAA,GAAQ,GAAA;AAGd,EAAA,OACE,OAAO,KAAA,CAAM,MAAA,KAAW,QAAA,IACxB,OAAO,MAAM,OAAA,KAAY,QAAA,KACxB,KAAA,CAAM,SAAA,KAAc,UAAa,OAAO,KAAA,CAAM,SAAA,KAAc,QAAA,CAAA,KAC5D,MAAM,GAAA,KAAQ,MAAA,IAAa,OAAO,KAAA,CAAM,QAAQ,QAAA,CAAA,KAChD,KAAA,CAAM,OAAA,KAAY,MAAA,IAAa,OAAO,KAAA,CAAM,OAAA,KAAY,QAAA,CAAA,KACxD,KAAA,CAAM,YAAY,MAAA,IAAa,OAAO,KAAA,CAAM,OAAA,KAAY,cACxD,KAAA,CAAM,KAAA,KAAU,MAAA,IAAa,OAAO,MAAM,KAAA,KAAU,QAAA,CAAA,KACpD,KAAA,CAAM,QAAA,KAAa,UAAa,OAAO,KAAA,CAAM,QAAA,KAAa,QAAA,CAAA,KAC1D,MAAM,cAAA,KAAmB,MAAA,IAAa,OAAO,KAAA,CAAM,mBAAmB,QAAA,CAAA,KACtE,KAAA,CAAM,SAAA,KAAc,MAAA,IAAa,OAAO,KAAA,CAAM,SAAA,KAAc,QAAA,CAAA,KAC5D,KAAA,CAAM,cAAc,MAAA,IAAa,OAAO,KAAA,CAAM,SAAA,KAAc,cAC5D,KAAA,CAAM,SAAA,KAAc,UAAa,KAAA,CAAM,OAAA,CAAQ,MAAM,SAAS,CAAA,CAAA;AAEnE;AAEA,SAAS,uBAAuB,GAAA,EAAqC;AACnE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,UAAU,OAAO,KAAA;AAE5C,EAAA,MAAM,QAAA,GAAW,GAAA;AAGjB,EAAA,IAAI,CAAC,QAAA,CAAS,OAAA,IAAW,OAAO,QAAA,CAAS,OAAA,KAAY,UAAU,OAAO,KAAA;AACtE,EAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AACzB,EAAA,IAAI,OAAO,OAAA,CAAQ,OAAA,KAAY,QAAA,EAAU,OAAO,KAAA;AAGhD,EAAA,IAAI,CAAC,OAAA,CAAQ,SAAA,EAAW,OAAO,KAAA;AAC/B,EAAA,IAAI,EAAE,OAAA,CAAQ,SAAA,YAAqB,UAAA,CAAA,EAAa;AAE9C,IAAA,MAAM,QAAQ,OAAA,CAAQ,SAAA;AACtB,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAE7B,MAAA,MAAM,IAAA,GAAO,OAAO,IAAA,CAAK,KAAK,EAAE,MAAA,CAAO,CAAA,GAAA,KAAO,CAAC,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,OAAO,CAAC,CAAA,GAAI,MAAA,CAAO,CAAC,CAAC,CAAA;AACvG,MAAA,IAAI,IAAA,CAAK,WAAW,EAAA,EAAI;AACtB,QAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,GAAA,KAAO,OAAO,KAAA,CAAM,GAAG,CAAC,CAAC,CAAA;AAChD,QAAA,IAAI,KAAA,CAAM,KAAA,CAAM,CAAA,CAAA,KAAK,OAAO,CAAA,KAAM,YAAY,CAAA,IAAK,CAAA,IAAK,CAAA,IAAK,GAAG,CAAA,EAAG;AACjE,UAAA,OAAA,CAAQ,SAAA,GAAY,IAAI,UAAA,CAAW,KAAK,CAAA;AAAA,QAC1C,CAAA,MAAO;AACL,UAAA,OAAO,KAAA;AAAA,QACT;AAAA,MACF,CAAA,MAAO;AACL,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF,CAAA,MAAO;AACL,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,QAAA,CAAS,aAAA,EAAe,OAAO,KAAA;AACpC,EAAA,IAAI,EAAE,QAAA,CAAS,aAAA,YAAyB,UAAA,CAAA,EAAa;AACnD,IAAA,MAAM,QAAQ,QAAA,CAAS,aAAA;AACvB,IAAA,IAAI,MAAM,IAAA,KAAS,QAAA,IAAY,MAAM,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA,EAAG;AACxD,MAAA,QAAA,CAAS,aAAA,GAAgB,IAAI,UAAA,CAAW,KAAA,CAAM,IAAgB,CAAA;AAAA,IAChE,CAAA,MAAO;AACL,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,QAAA,CAAS,SAAA,EAAW,OAAO,KAAA;AAChC,EAAA,IAAI,EAAE,QAAA,CAAS,SAAA,YAAqB,UAAA,CAAA,EAAa;AAC/C,IAAA,MAAM,SAAS,QAAA,CAAS,SAAA;AACxB,IAAA,IAAI,OAAO,IAAA,KAAS,QAAA,IAAY,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA,EAAG;AAC1D,MAAA,QAAA,CAAS,SAAA,GAAY,IAAI,UAAA,CAAW,MAAA,CAAO,IAAgB,CAAA;AAAA,IAC7D,CAAA,MAAO;AACL,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,CAAC,QAAA,CAAS,OAAA,IAAW,OAAO,QAAA,CAAS,YAAY,QAAA,EAAU;AAC7D,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAU,QAAA,CAAS,OAAA;AAGzB,EAAA,IAAI,OAAO,OAAA,KAAY,QAAA,IAAY,OAAA,KAAY,IAAA,EAAM;AACnD,IAAA,MAAM,UAAA,GAAa,OAAA;AACnB,IAAA,IAAI,CAAC,UAAA,CAAW,OAAA,IAAW,QAAA,CAAS,yBAAyB,UAAA,EAAY;AACvE,MAAA,IAAI;AACF,QAAA,MAAM,oBAAoB,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,SAAS,aAAa,CAAA;AACzE,QAAA,MAAM,KAAA,GAAQ,iBAAA,CAAkB,KAAA,CAAM,IAAI,CAAA;AAC1C,QAAA,IAAI,KAAA,CAAM,UAAU,CAAA,EAAG;AACrB,UAAA,MAAM,OAAA,GAAU,KAAA,CAAM,CAAC,CAAA,CAAE,IAAA,EAAK;AAC9B,UAAA,IAAI,OAAA,IAAW,sBAAA,CAAuB,IAAA,CAAK,OAAO,CAAA,EAAG;AACnD,YAAA,UAAA,CAAW,OAAA,GAAU,OAAA;AAAA,UACvB;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,mBAAA,CAAoB,QAAA,CAAS,OAAO,CAAA,EAAG;AAC1C,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT;AAEA,eAAsB,iBACpB,KAAA,EACyB;AACzB,EAAA,MAAM,CAAC,EAAE,CAAA,GAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AACpC,EAAA,IAAI,OAAO,QAAA,EAAU;AACnB,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AAGA,EAAA,IAAI,CAAC,KAAA,CAAM,iBAAA,IAAqB,CAAC,sBAAA,CAAuB,KAAA,CAAM,iBAAiB,CAAA,EAAG;AAChF,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AAEA,EAAA,IAAI;AAEF,IAAA,MAAM,WAAW,KAAA,CAAM,iBAAA;AAEvB,IAAA,MAAM,oBAAoB,IAAI,WAAA,EAAY,CAAE,MAAA,CAAO,SAAS,aAAa,CAAA;AACzE,IAAA,MAAM,aAAA,GAAgB,iBAAiB,iBAAiB,CAAA;AAExD,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,IAChD;AAGA,IAAA,IAAI,CAAC,mBAAA,CAAoB,aAAA,EAAe,QAAA,CAAS,OAAoB,CAAA,EAAG;AACtE,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,IAChD;AAGA,IAAA,MAAM,oBAAA,GAAuB,kBAAkB,aAAa,CAAA;AAC5D,IAAA,IAAI,yBAAyB,iBAAA,EAAmB;AAC9C,MAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,IAChD;AAGA,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,IAAA,CAAK,QAAA,CAAS,MAAA;AAAA,MAClC,QAAA,CAAS,aAAA;AAAA,MACT,QAAA,CAAS,SAAA;AAAA,MACT,SAAS,OAAA,CAAQ;AAAA,KACnB;AAEA,IAAA,OAAO;AAAA,MACL,GAAG,KAAA;AAAA,MACH,MAAA,EAAQ,QAAA,GAAW,WAAA,CAAY,QAAA,GAAW,WAAA,CAAY;AAAA,KACxD;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AACF;AAIA,SAAS,iBAAiB,OAAA,EAA2C;AACnE,EAAA,IAAI;AACF,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,KAAA,CAAM,IAAI,CAAA;AAGhC,IAAA,MAAM,MAAA,GAAS,YAAY,KAAK,CAAA;AAChC,IAAA,IAAI,CAAC,QAAQ,OAAO,IAAA;AAEpB,IAAA,MAAM,MAAA,GAA4B,EAAE,GAAG,MAAA,EAAO;AAE9C,IAAA,IAAI,SAAA,GAAY,CAAA;AAGhB,IAAA,MAAM,eAAA,GAAkB,cAAA,CAAe,KAAA,EAAO,SAAS,CAAA;AACvD,IAAA,IAAI,eAAA,CAAgB,cAAc,KAAA,CAAA,EAAW;AAC3C,MAAA,MAAA,CAAO,YAAY,eAAA,CAAgB,SAAA;AACnC,MAAA,SAAA,GAAY,eAAA,CAAgB,SAAA;AAAA,IAC9B;AAGA,IAAA,MAAM,cAAA,GAAiB,mBAAA,CAAoB,KAAA,EAAO,SAAS,CAAA;AAC3D,IAAA,MAAA,CAAO,MAAA,CAAO,QAAQ,cAAc,CAAA;AAEpC,IAAA,OAAO,MAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEA,SAAS,YAAY,KAAA,EAA6D;AAEhF,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,CAAC,CAAA,EAAG,MAAM,uDAAuD,CAAA;AAC3F,EAAA,IAAI,CAAC,aAAa,OAAO,IAAA;AAEzB,EAAA,MAAM,MAAA,GAAS,YAAY,CAAC,CAAA;AAG5B,EAAA,MAAM,OAAA,GAAU,MAAM,CAAC,CAAA;AACvB,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,uBAAuB,IAAA,CAAK,OAAO,GAAG,OAAO,IAAA;AAE9D,EAAA,OAAO,EAAE,QAAQ,OAAA,EAAQ;AAC3B;AAEA,SAAS,cAAA,CAAe,OAAiB,UAAA,EAA+D;AACtG,EAAA,IAAI,SAAA,GAAY,UAAA;AAGhB,EAAA,IAAI,KAAA,CAAM,SAAS,CAAA,KAAM,EAAA,IAAM,MAAM,SAAA,GAAY,CAAC,CAAA,IAAK,CAAC,MAAM,SAAA,GAAY,CAAC,CAAA,CAAE,QAAA,CAAS,GAAG,CAAA,EAAG;AAC1F,IAAA,SAAA,EAAA;AACA,IAAA,MAAM,SAAA,GAAY,MAAM,SAAS,CAAA;AACjC,IAAA,SAAA,EAAA;AAGA,IAAA,IAAI,KAAA,CAAM,SAAS,CAAA,KAAM,EAAA,EAAI;AAC3B,MAAA,SAAA,EAAA;AAAA,IACF;AAEA,IAAA,OAAO,EAAE,SAAA,EAAW,SAAA,EAAW,SAAA,EAAU;AAAA,EAC3C;AAEA,EAAA,OAAO,EAAE,WAAW,SAAA,EAAU;AAChC;AAEA,SAAS,mBAAA,CAAoB,OAAiB,UAAA,EAAgD;AAC5F,EAAA,MAAM,SAAqC,EAAC;AAG5C,EAAA,MAAM,YAAA,GAGD;AAAA,IACH,EAAE,MAAA,EAAQ,OAAA,EAAS,GAAA,EAAK,KAAA,EAAM;AAAA,IAC9B,EAAE,MAAA,EAAQ,WAAA,EAAa,GAAA,EAAK,SAAA,EAAU;AAAA,IACtC,EAAE,MAAA,EAAQ,YAAA,EAAc,GAAA,EAAK,SAAA,EAAU;AAAA,IACvC,EAAE,MAAA,EAAQ,SAAA,EAAW,GAAA,EAAK,OAAA,EAAQ;AAAA,IAClC,EAAE,MAAA,EAAQ,aAAA,EAAe,GAAA,EAAK,UAAA,EAAW;AAAA,IACzC,EAAE,MAAA,EAAQ,mBAAA,EAAqB,GAAA,EAAK,gBAAA,EAAiB;AAAA,IACrD,EAAE,MAAA,EAAQ,cAAA,EAAgB,GAAA,EAAK,WAAA,EAAY;AAAA,IAC3C,EAAE,MAAA,EAAQ,cAAA,EAAgB,GAAA,EAAK,WAAA;AAAY,GAC7C;AAEA,EAAA,IAAI,SAAA,GAAY,UAAA;AAEhB,EAAA,OAAO,SAAA,GAAY,MAAM,MAAA,EAAQ;AAC/B,IAAA,MAAM,IAAA,GAAO,MAAM,SAAS,CAAA;AAC5B,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA,SAAA,EAAA;AACA,MAAA;AAAA,IACF;AAGA,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,YAAY,CAAA,EAAG;AACjC,MAAA,MAAM,SAAA,GAAY,cAAA,CAAe,KAAA,EAAO,SAAA,GAAY,CAAC,CAAA;AACrD,MAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,QAAA,MAAA,CAAO,SAAA,GAAY,SAAA;AACnB,QAAA,SAAA,IAAa,UAAU,MAAA,GAAS,CAAA;AAChC,QAAA;AAAA,MACF;AAAA,IACF;AAIA,IAAA,KAAA,MAAW,EAAE,MAAA,EAAQ,GAAA,EAAI,IAAK,YAAA,EAAc;AAC1C,MAAA,IAAI,IAAA,CAAK,UAAA,CAAW,MAAM,CAAA,EAAG;AAC3B,QAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,MAAM,CAAA;AAC1C,QAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAEd,QAAA;AAAA,MACF;AAAA,IACF;AAMA,IAAA,SAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,cAAA,CAAe,OAAiB,UAAA,EAA8B;AACrE,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,IAAI,SAAA,GAAY,UAAA;AAEhB,EAAA,OAAO,SAAA,GAAY,MAAM,MAAA,IAAU,KAAA,CAAM,SAAS,CAAA,EAAG,UAAA,CAAW,IAAI,CAAA,EAAG;AACrE,IAAA,SAAA,CAAU,KAAK,KAAA,CAAM,SAAS,CAAA,CAAE,SAAA,CAAU,CAAC,CAAC,CAAA;AAC5C,IAAA,SAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,SAAA;AACT;AAGA,SAAS,mBAAA,CAAoB,QAA2B,KAAA,EAA2B;AAEjF,EAAA,IAAI,OAAO,MAAA,KAAW,KAAA,CAAM,UAAU,MAAA,CAAO,OAAA,KAAY,MAAM,OAAA,EAAS;AACtE,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,gBAAA,GAID;AAAA,IACH,EAAE,QAAA,EAAU,WAAA,EAAa,SAAA,EAAW,WAAA,EAAY;AAAA,IAChD,EAAE,QAAA,EAAU,KAAA,EAAO,SAAA,EAAW,KAAA,EAAM;AAAA,IACpC,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,SAAA,EAAU;AAAA,IAC5C,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,EAAW,SAAA,EAAU;AAAA,IAC5C,EAAE,QAAA,EAAU,OAAA,EAAS,SAAA,EAAW,OAAA,EAAQ;AAAA,IACxC,EAAE,QAAA,EAAU,UAAA,EAAY,SAAA,EAAW,UAAA,EAAW;AAAA,IAC9C,EAAE,QAAA,EAAU,gBAAA,EAAkB,SAAA,EAAW,gBAAA,EAAiB;AAAA,IAC1D,EAAE,QAAA,EAAU,WAAA,EAAa,SAAA,EAAW,WAAA,EAAY;AAAA,IAChD,EAAE,QAAA,EAAU,WAAA,EAAa,SAAA,EAAW,WAAA,EAAY;AAAA,IAChD;AAAA,MACE,QAAA,EAAU,WAAA;AAAA,MACV,SAAA,EAAW,WAAA;AAAA,MACX,SAAA,EAAW,CAAC,UAAA,EAAY,WAAA,KAAgB;AACtC,QAAA,IAAI,CAAC,MAAM,OAAA,CAAQ,UAAU,KAAK,CAAC,KAAA,CAAM,OAAA,CAAQ,WAAW,CAAA,EAAG;AAC7D,UAAA,OAAO,KAAA;AAAA,QACT;AACA,QAAA,OAAO,UAAA,CAAW,MAAA,KAAW,WAAA,CAAY,MAAA,IAClC,UAAA,CAAW,KAAA,CAAM,CAAC,IAAA,EAAM,KAAA,KAAU,IAAA,KAAS,WAAA,CAAY,KAAK,CAAC,CAAA;AAAA,MACtE;AAAA;AACF,GACF;AAGA,EAAA,KAAA,MAAW,EAAE,QAAA,EAAU,SAAA,EAAW,SAAA,MAAe,gBAAA,EAAkB;AACjE,IAAA,MAAM,UAAA,GAAa,MAAM,QAAQ,CAAA;AACjC,IAAA,MAAM,WAAA,GAAc,OAAO,SAAS,CAAA;AAEpC,IAAA,IAAI,eAAe,MAAA,EAAW;AAC5B,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,IAAI,CAAC,SAAA,CAAU,UAAA,EAAY,WAAW,CAAA,EAAG;AACvC,UAAA,OAAO,KAAA;AAAA,QACT;AAAA,MACF,CAAA,MAAA,IAAW,eAAe,WAAA,EAAa;AACrC,QAAA,OAAO,KAAA;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAGA,EAAA,OAAO,mBAAmB,MAAM,CAAA;AAClC;AAGA,SAAS,mBAAmB,MAAA,EAAoC;AAC9D,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAGrB,EAAA,IAAI,OAAO,QAAA,EAAU;AACnB,IAAA,MAAM,QAAA,GAAW,IAAI,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AACzC,IAAA,MAAM,SAAA,GAAY,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,GAAA;AACjC,IAAA,MAAM,WAAW,IAAA,CAAK,GAAA,CAAI,QAAA,CAAS,OAAA,KAAY,GAAG,CAAA;AAClD,IAAA,IAAI,WAAW,SAAA,EAAW;AACxB,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,cAAA,EAAgB;AACzB,IAAA,MAAM,cAAA,GAAiB,IAAI,IAAA,CAAK,MAAA,CAAO,cAAc,CAAA;AACrD,IAAA,IAAI,cAAA,CAAe,OAAA,EAAQ,IAAK,GAAA,EAAK;AACnC,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAGA,EAAA,IAAI,OAAO,SAAA,EAAW;AACpB,IAAA,MAAM,SAAA,GAAY,IAAI,IAAA,CAAK,MAAA,CAAO,SAAS,CAAA;AAC3C,IAAA,IAAI,SAAA,CAAU,OAAA,EAAQ,GAAI,GAAA,EAAK;AAC7B,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,IAAA;AACT;AAIA,SAAS,kBAAkB,KAAA,EAAkC;AAC3D,EAAA,IAAI,OAAA,GAAU,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA;AAAA,CAAA;AAC7B,EAAA,OAAA,IAAW,CAAA,EAAG,MAAM,OAAO,CAAA,CAAA;AAE3B,EAAA,IAAI,MAAM,SAAA,EAAW;AACnB,IAAA,OAAA,IAAW;;AAAA,EAAO,MAAM,SAAS,CAAA,CAAA;AAAA,EACnC;AAEA,EAAA,MAAM,MAAA,GAAS,gBAAgB,KAAK,CAAA;AAEpC,EAAA,IAAI,OAAO,MAAA,EAAQ;AACjB,IAAA,OAAA,IAAW;;AAAA,EAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA;AAAA,EACrC;AAEA,EAAA,OAAO,OAAA;AACT;AAEA,SAAS,gBAAgB,KAAA,EAAoC;AAC3D,EAAA,MAAM,SAAmB,EAAC;AAG1B,EAAA,MAAM,aAAA,GAID;AAAA,IACH,EAAE,GAAA,EAAK,KAAA,EAAO,MAAA,EAAQ,OAAA,EAAQ;AAAA,IAC9B,EAAE,GAAA,EAAK,SAAA,EAAW,MAAA,EAAQ,WAAA,EAAY;AAAA,IACtC,EAAE,GAAA,EAAK,SAAA,EAAW,MAAA,EAAQ,YAAA,EAAa;AAAA,IACvC,EAAE,GAAA,EAAK,OAAA,EAAS,MAAA,EAAQ,SAAA,EAAU;AAAA,IAClC,EAAE,GAAA,EAAK,UAAA,EAAY,MAAA,EAAQ,aAAA,EAAc;AAAA,IACzC,EAAE,GAAA,EAAK,gBAAA,EAAkB,MAAA,EAAQ,mBAAA,EAAoB;AAAA,IACrD,EAAE,GAAA,EAAK,WAAA,EAAa,MAAA,EAAQ,cAAA,EAAe;AAAA,IAC3C,EAAE,GAAA,EAAK,WAAA,EAAa,MAAA,EAAQ,cAAA,EAAe;AAAA,IAC3C;AAAA,MACE,GAAA,EAAK,WAAA;AAAA,MACL,MAAA,EAAQ,YAAA;AAAA,MACR,SAAA,EAAW,CAAC,KAAA,KAAU;AACpB,QAAA,IAAI,MAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,KAAA,CAAM,SAAS,CAAA,EAAG;AAC5C,UAAA,OAAO,CAAC,cAAc,GAAG,KAAA,CAAM,IAAI,CAAA,QAAA,KAAY,CAAA,EAAA,EAAK,QAAQ,CAAA,CAAE,CAAC,CAAA;AAAA,QACjE;AACA,QAAA,OAAO,EAAC;AAAA,MACV;AAAA;AACF,GACF;AAEA,EAAA,KAAA,MAAW,EAAE,GAAA,EAAK,MAAA,EAAQ,SAAA,MAAe,aAAA,EAAe;AACtD,IAAA,MAAM,KAAA,GAAQ,MAAM,GAAG,CAAA;AACvB,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,MAAM,SAAA,GAAY,UAAU,KAAK,CAAA;AACjC,QAAA,MAAA,CAAO,IAAA,CAAK,GAAG,SAAS,CAAA;AAAA,MAC1B,CAAA,MAAA,IAAW,OAAO,KAAA,KAAU,QAAA,EAAU;AACpC,QAAA,MAAA,CAAO,IAAA,CAAK,CAAA,EAAG,MAAM,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT","file":"solana-ZARDAF6O.js","sourcesContent":["import nacl from \"tweetnacl\";\nimport { ProofStatus, SignatureProof, type SIWXInput, type SolanaMetadata } from \"@notabene/javascript-sdk\";\nimport { base64, base58 } from \"@scure/base\";\n\ninterface ParsedSIWSMessage {\n domain: string;\n address: string;\n statement?: string;\n uri?: string;\n version?: string;\n chainId?: string;\n nonce?: string;\n issuedAt?: string;\n expirationTime?: string;\n notBefore?: string;\n requestId?: string;\n resources?: string[];\n}\n\n\n\n/**\n * Verifies a Solana signature proof.\n * \n * This function can verify two types of Solana signatures:\n * 1. Standard Solana signatures\n * \n * @param proof - The signature proof containing the address, attestation, and signature\n * @returns Promise that resolves to a SignatureProof with updated status (VERIFIED or FAILED)\n * \n * @example\n * // Standard Solana signature verification\n * const result = await verifySolanaSignature(proof);\n * \n */\nexport async function verifySolanaSignature(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"solana\") return { ...proof, status: ProofStatus.FAILED };\n\n try {\n const publicKey = base58.decode(address);\n const messageBytes = new TextEncoder().encode(proof.attestation);\n const signatureBytes = base64.decode(proof.proof);\n const verified = nacl.sign.detached.verify(\n messageBytes,\n signatureBytes,\n publicKey,\n );\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n\nfunction isSolanaSignInInput(obj: unknown): obj is SIWXInput {\n if (!obj || typeof obj !== 'object') return false;\n \n const input = obj as Record<string, unknown>;\n \n // Check for required properties\n return (\n typeof input.domain === 'string' &&\n typeof input.address === 'string' &&\n (input.statement === undefined || typeof input.statement === 'string') &&\n (input.uri === undefined || typeof input.uri === 'string') &&\n (input.version === undefined || typeof input.version === 'string') &&\n (input.chainId === undefined || typeof input.chainId === 'string') &&\n (input.nonce === undefined || typeof input.nonce === 'string') &&\n (input.issuedAt === undefined || typeof input.issuedAt === 'string') &&\n (input.expirationTime === undefined || typeof input.expirationTime === 'string') &&\n (input.notBefore === undefined || typeof input.notBefore === 'string') &&\n (input.requestId === undefined || typeof input.requestId === 'string') &&\n (input.resources === undefined || Array.isArray(input.resources))\n );\n}\n\nfunction isSolanaSignInMetadata(obj: unknown): obj is SolanaMetadata {\n if (!obj || typeof obj !== 'object') return false;\n \n const metadata = obj as Record<string, unknown>;\n \n // Check account object\n if (!metadata.account || typeof metadata.account !== 'object') return false;\n const account = metadata.account as Record<string, unknown>;\n if (typeof account.address !== 'string') return false;\n \n // Handle publicKey - could be Uint8Array or serialized object with numeric keys\n if (!account.publicKey) return false;\n if (!(account.publicKey instanceof Uint8Array)) {\n // Try to convert from serialized format\n const pkObj = account.publicKey as Record<string, unknown>;\n if (typeof pkObj === 'object') {\n // Convert object with numeric keys to Uint8Array\n const keys = Object.keys(pkObj).filter(key => !isNaN(Number(key))).sort((a, b) => Number(a) - Number(b));\n if (keys.length === 32) { // Solana public keys are 32 bytes\n const bytes = keys.map(key => Number(pkObj[key]));\n if (bytes.every(b => typeof b === 'number' && b >= 0 && b <= 255)) {\n account.publicKey = new Uint8Array(bytes);\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n return false;\n }\n }\n \n // Handle signedMessage - could be Uint8Array or Buffer-like object\n if (!metadata.signedMessage) return false;\n if (!(metadata.signedMessage instanceof Uint8Array)) {\n const smObj = metadata.signedMessage as Record<string, unknown>;\n if (smObj.type === 'Buffer' && Array.isArray(smObj.data)) {\n metadata.signedMessage = new Uint8Array(smObj.data as number[]);\n } else {\n return false;\n }\n }\n \n // Handle signature - could be Uint8Array or Buffer-like object\n if (!metadata.signature) return false;\n if (!(metadata.signature instanceof Uint8Array)) {\n const sigObj = metadata.signature as Record<string, unknown>;\n if (sigObj.type === 'Buffer' && Array.isArray(sigObj.data)) {\n metadata.signature = new Uint8Array(sigObj.data as number[]);\n } else {\n return false;\n }\n }\n \n // Check message field contains valid SolanaSignInInput\n if (!metadata.message || typeof metadata.message !== 'object') {\n return false;\n }\n \n const message = metadata.message as unknown;\n \n // If address is missing from message, try to extract it from signedMessage\n if (typeof message === 'object' && message !== null) {\n const messageObj = message as Record<string, unknown>;\n if (!messageObj.address && metadata.signedMessage instanceof Uint8Array) {\n try {\n const signedMessageText = new TextDecoder().decode(metadata.signedMessage);\n const lines = signedMessageText.split('\\n');\n if (lines.length >= 2) {\n const address = lines[1].trim();\n if (address && /^[a-zA-Z0-9]{32,44}$/.test(address)) {\n messageObj.address = address;\n }\n }\n } catch {\n // Ignore errors in address extraction\n }\n }\n }\n \n if (!isSolanaSignInInput(metadata.message)) {\n return false;\n }\n \n return true;\n}\n\nexport async function verifySolanaSIWS(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns] = proof.address.split(/:/);\n if (ns !== \"solana\") {\n return { ...proof, status: ProofStatus.FAILED };\n }\n \n // Validate that metadata conforms to SolanaSignInMetadata\n if (!proof.chainSpecificData || !isSolanaSignInMetadata(proof.chainSpecificData)) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n\n try {\n // Now we can safely cast to SolanaMetadata since we validated it\n const metadata = proof.chainSpecificData as SolanaMetadata;\n \n const signedMessageText = new TextDecoder().decode(metadata.signedMessage);\n const parsedMessage = parseSIWSMessage(signedMessageText);\n \n if (!parsedMessage) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n\n // Validate the parsed message against the input\n if (!validateSIWSMessage(parsedMessage, metadata.message as SIWXInput)) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n\n // Reconstruct the message to ensure it matches the signed message\n const reconstructedMessage = createSIWSMessage(parsedMessage);\n if (reconstructedMessage !== signedMessageText) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n\n // Verify the signature against the message\n const verified = nacl.sign.detached.verify(\n metadata.signedMessage,\n metadata.signature,\n metadata.account.publicKey as Uint8Array\n );\n \n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n\n// Parse SIWS message according to ABNF format\n// https://github.com/phantom/sign-in-with-solana/blob/e4060d2916469116d5080a712feaf81ea1db4f65/README.md#message-construction\nfunction parseSIWSMessage(message: string): ParsedSIWSMessage | null {\n try {\n const lines = message.split('\\n');\n \n // Parse header (domain and address)\n const header = parseHeader(lines);\n if (!header) return null;\n \n const result: ParsedSIWSMessage = { ...header };\n \n let lineIndex = 2;\n \n // Parse statement if present\n const statementResult = parseStatement(lines, lineIndex);\n if (statementResult.statement !== undefined) {\n result.statement = statementResult.statement;\n lineIndex = statementResult.nextIndex;\n }\n \n // Parse advanced fields\n const advancedFields = parseAdvancedFields(lines, lineIndex);\n Object.assign(result, advancedFields);\n \n return result;\n } catch {\n return null;\n }\n}\n\nfunction parseHeader(lines: string[]): { domain: string; address: string } | null {\n // First line: domain + \" wants you to sign in with your Solana account:\"\n const domainMatch = lines[0]?.match(/^(.+) wants you to sign in with your Solana account:$/);\n if (!domainMatch) return null;\n \n const domain = domainMatch[1];\n \n // Second line: address\n const address = lines[1];\n if (!address || !/^[a-zA-Z0-9]{32,44}$/.test(address)) return null;\n \n return { domain, address };\n}\n\nfunction parseStatement(lines: string[], startIndex: number): { statement?: string; nextIndex: number } {\n let lineIndex = startIndex;\n \n // Check for statement (after empty line)\n if (lines[lineIndex] === '' && lines[lineIndex + 1] && !lines[lineIndex + 1].includes(':')) {\n lineIndex++; // Skip empty line\n const statement = lines[lineIndex];\n lineIndex++;\n \n // Skip another empty line after statement\n if (lines[lineIndex] === '') {\n lineIndex++;\n }\n \n return { statement, nextIndex: lineIndex };\n }\n \n return { nextIndex: lineIndex };\n}\n\nfunction parseAdvancedFields(lines: string[], startIndex: number): Partial<ParsedSIWSMessage> {\n const result: Partial<ParsedSIWSMessage> = {};\n \n // Define field parsers for string fields only\n const fieldParsers: Array<{\n prefix: string;\n key: keyof Omit<ParsedSIWSMessage, 'resources'>;\n }> = [\n { prefix: 'URI: ', key: 'uri' },\n { prefix: 'Version: ', key: 'version' },\n { prefix: 'Chain ID: ', key: 'chainId' },\n { prefix: 'Nonce: ', key: 'nonce' },\n { prefix: 'Issued At: ', key: 'issuedAt' },\n { prefix: 'Expiration Time: ', key: 'expirationTime' },\n { prefix: 'Not Before: ', key: 'notBefore' },\n { prefix: 'Request ID: ', key: 'requestId' }\n ];\n \n let lineIndex = startIndex;\n \n while (lineIndex < lines.length) {\n const line = lines[lineIndex];\n if (!line) {\n lineIndex++;\n continue;\n }\n \n // Check for resources (special case)\n if (line.startsWith('Resources:')) {\n const resources = parseResources(lines, lineIndex + 1);\n if (resources.length > 0) {\n result.resources = resources;\n lineIndex += resources.length + 1; // +1 for the \"Resources:\" line\n continue;\n }\n }\n \n // Check for other fields\n let fieldFound = false;\n for (const { prefix, key } of fieldParsers) {\n if (line.startsWith(prefix)) {\n const value = line.substring(prefix.length);\n result[key] = value;\n fieldFound = true;\n break;\n }\n }\n \n if (!fieldFound) {\n // Unknown field, skip it\n }\n \n lineIndex++;\n }\n \n return result;\n}\n\nfunction parseResources(lines: string[], startIndex: number): string[] {\n const resources: string[] = [];\n let lineIndex = startIndex;\n \n while (lineIndex < lines.length && lines[lineIndex]?.startsWith('- ')) {\n resources.push(lines[lineIndex].substring(2));\n lineIndex++;\n }\n \n return resources;\n}\n\n// Validate parsed SIWS message against input\nfunction validateSIWSMessage(parsed: ParsedSIWSMessage, input: SIWXInput): boolean {\n // Required fields validation\n if (parsed.domain !== input.domain || parsed.address !== input.address) {\n return false;\n }\n \n // Define validation rules for optional fields\n const fieldValidations: Array<{\n inputKey: keyof SIWXInput;\n parsedKey: keyof ParsedSIWSMessage;\n validator?: (inputValue: unknown, parsedValue: unknown) => boolean;\n }> = [\n { inputKey: 'statement', parsedKey: 'statement' },\n { inputKey: 'uri', parsedKey: 'uri' },\n { inputKey: 'version', parsedKey: 'version' },\n { inputKey: 'chainId', parsedKey: 'chainId' },\n { inputKey: 'nonce', parsedKey: 'nonce' },\n { inputKey: 'issuedAt', parsedKey: 'issuedAt' },\n { inputKey: 'expirationTime', parsedKey: 'expirationTime' },\n { inputKey: 'notBefore', parsedKey: 'notBefore' },\n { inputKey: 'requestId', parsedKey: 'requestId' },\n {\n inputKey: 'resources',\n parsedKey: 'resources',\n validator: (inputValue, parsedValue) => {\n if (!Array.isArray(inputValue) || !Array.isArray(parsedValue)) {\n return false;\n }\n return inputValue.length === parsedValue.length && \n inputValue.every((item, index) => item === parsedValue[index]);\n }\n }\n ];\n \n // Validate optional fields\n for (const { inputKey, parsedKey, validator } of fieldValidations) {\n const inputValue = input[inputKey];\n const parsedValue = parsed[parsedKey];\n \n if (inputValue !== undefined) {\n if (validator) {\n if (!validator(inputValue, parsedValue)) {\n return false;\n }\n } else if (inputValue !== parsedValue) {\n return false;\n }\n }\n }\n \n // Validate timestamps\n return validateTimestamps(parsed);\n}\n\n// Separate timestamp validation for better testability and clarity\nfunction validateTimestamps(parsed: ParsedSIWSMessage): boolean {\n const now = Date.now();\n \n // Validate issuedAt (allow 24 hour threshold for testing)\n if (parsed.issuedAt) {\n const issuedAt = new Date(parsed.issuedAt);\n const threshold = 24 * 60 * 60 * 1000; // 24 hours in milliseconds\n const timeDiff = Math.abs(issuedAt.getTime() - now);\n if (timeDiff > threshold) {\n return false;\n }\n }\n \n // Validate expirationTime\n if (parsed.expirationTime) {\n const expirationTime = new Date(parsed.expirationTime);\n if (expirationTime.getTime() <= now) {\n return false; // Message has expired\n }\n }\n \n // Validate notBefore\n if (parsed.notBefore) {\n const notBefore = new Date(parsed.notBefore);\n if (notBefore.getTime() > now) {\n return false; // Message not yet valid\n }\n }\n \n return true;\n}\n\n// Create SIWS message string according to ABNF format\n// https://github.com/phantom/sign-in-with-solana/blob/e4060d2916469116d5080a712feaf81ea1db4f65/README.md#abnf-message-format\nfunction createSIWSMessage(input: ParsedSIWSMessage): string {\n let message = `${input.domain} wants you to sign in with your Solana account:\\n`;\n message += `${input.address}`;\n\n if (input.statement) {\n message += `\\n\\n${input.statement}`;\n }\n\n const fields = buildFieldLines(input);\n \n if (fields.length) {\n message += `\\n\\n${fields.join('\\n')}`;\n }\n\n return message;\n}\n\nfunction buildFieldLines(input: ParsedSIWSMessage): string[] {\n const fields: string[] = [];\n \n // Define field mappings\n const fieldMappings: Array<{\n key: keyof ParsedSIWSMessage;\n prefix: string;\n formatter?: (value: unknown) => string[];\n }> = [\n { key: 'uri', prefix: 'URI: ' },\n { key: 'version', prefix: 'Version: ' },\n { key: 'chainId', prefix: 'Chain ID: ' },\n { key: 'nonce', prefix: 'Nonce: ' },\n { key: 'issuedAt', prefix: 'Issued At: ' },\n { key: 'expirationTime', prefix: 'Expiration Time: ' },\n { key: 'notBefore', prefix: 'Not Before: ' },\n { key: 'requestId', prefix: 'Request ID: ' },\n {\n key: 'resources',\n prefix: 'Resources:',\n formatter: (value) => {\n if (Array.isArray(value) && value.length > 0) {\n return ['Resources:', ...value.map(resource => `- ${resource}`)];\n }\n return [];\n }\n }\n ];\n \n for (const { key, prefix, formatter } of fieldMappings) {\n const value = input[key];\n if (value !== undefined) {\n if (formatter) {\n const formatted = formatter(value);\n fields.push(...formatted);\n } else if (typeof value === 'string') {\n fields.push(`${prefix}${value}`);\n }\n }\n }\n \n return fields;\n}\n"]}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { ProofStatus } from '@notabene/javascript-sdk';
|
|
3
|
+
import { Hex, Signature, Secp256k1, Hash, PublicKey, Bytes } from 'ox';
|
|
4
|
+
import { base58 } from '@scure/base';
|
|
5
|
+
|
|
6
|
+
if (typeof globalThis !== 'undefined' && !globalThis.Buffer) { globalThis.Buffer = Buffer; }
|
|
7
|
+
function verifyTIP191(address, message, proof) {
|
|
8
|
+
try {
|
|
9
|
+
const payload = getSignPayload(Hex.fromString(message));
|
|
10
|
+
const signature = Signature.fromHex(proof);
|
|
11
|
+
const publicKey = Secp256k1.recoverPublicKey({ payload, signature });
|
|
12
|
+
const hex = `0x41${Hash.keccak256(
|
|
13
|
+
`0x${PublicKey.toHex(publicKey).slice(4)}`
|
|
14
|
+
).substring(26)}`;
|
|
15
|
+
const bytes = Bytes.from(hex);
|
|
16
|
+
const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);
|
|
17
|
+
const checked = Bytes.concat(bytes, checksum);
|
|
18
|
+
const b58 = base58.encode(checked);
|
|
19
|
+
return b58 === address;
|
|
20
|
+
} catch (error) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
async function verifyPersonalSignTIP191(proof) {
|
|
25
|
+
const [ns, , address] = proof.address.split(/:/);
|
|
26
|
+
if (ns !== "tron") return { ...proof, status: ProofStatus.FAILED };
|
|
27
|
+
const verified = verifyTIP191(
|
|
28
|
+
address,
|
|
29
|
+
proof.attestation,
|
|
30
|
+
proof.proof
|
|
31
|
+
);
|
|
32
|
+
return {
|
|
33
|
+
...proof,
|
|
34
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function encode(data) {
|
|
38
|
+
const message = Hex.from(data);
|
|
39
|
+
return Hex.concat(
|
|
40
|
+
// Personal Sign Format: `0x19 ‖ "Ethereum Signed Message:\n" ‖ message.length ‖ message`
|
|
41
|
+
"0x19",
|
|
42
|
+
Hex.fromString("TRON Signed Message:\n" + Hex.size(message)),
|
|
43
|
+
message
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
function getSignPayload(data) {
|
|
47
|
+
return Hash.keccak256(encode(data));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { encode, getSignPayload, verifyPersonalSignTIP191, verifyTIP191 };
|
|
51
|
+
//# sourceMappingURL=tron-FI2B6DRS.js.map
|
|
52
|
+
//# sourceMappingURL=tron-FI2B6DRS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tron.ts"],"names":[],"mappings":";;;;;;AAIO,SAAS,YAAA,CACd,OAAA,EACA,OAAA,EACA,KAAA,EACS;AACT,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,cAAA,CAAe,GAAA,CAAI,UAAA,CAAW,OAAO,CAAC,CAAA;AACtD,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,OAAA,CAAQ,KAAK,CAAA;AACzC,IAAA,MAAM,YAAY,SAAA,CAAU,gBAAA,CAAiB,EAAE,OAAA,EAAS,WAAW,CAAA;AACnE,IAAA,MAAM,GAAA,GAAe,OAAO,IAAA,CAAK,SAAA;AAAA,MAC/B,KAAK,SAAA,CAAU,KAAA,CAAM,SAAS,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,KAC1C,CAAE,SAAA,CAAU,EAAE,CAAC,CAAA,CAAA;AACf,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,IAAA,CAAK,GAAG,CAAA;AAC5B,IAAA,MAAM,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,GAAG,CAAC,CAAC,CAAA,CAAE,KAAA,CAAM,GAAG,CAAC,CAAA;AACrE,IAAA,MAAM,OAAA,GAAU,KAAA,CAAM,MAAA,CAAO,KAAA,EAAO,QAAQ,CAAA;AAC5C,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,CAAO,OAAO,CAAA;AACjC,IAAA,OAAO,GAAA,KAAQ,OAAA;AAAA,EAEjB,SAAS,KAAA,EAAO;AACd,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,eAAsB,yBACpB,KAAA,EACyB;AACzB,EAAA,MAAM,CAAC,MAAM,OAAO,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC/C,EAAA,IAAI,EAAA,KAAO,QAAQ,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAEjE,EAAA,MAAM,QAAA,GAAW,YAAA;AAAA,IACf,OAAA;AAAA,IACA,KAAA,CAAM,WAAA;AAAA,IACN,KAAA,CAAM;AAAA,GACR;AACA,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,MAAA,EAAQ,QAAA,GAAW,WAAA,CAAY,QAAA,GAAW,WAAA,CAAY;AAAA,GACxD;AACF;AAEO,SAAS,OAAO,IAAA,EAAsC;AAC3D,EAAA,MAAM,OAAA,GAAU,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA;AAC7B,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA;AAAA,IAET,MAAA;AAAA,IACA,IAAI,UAAA,CAAW,wBAAA,GAA2B,GAAA,CAAI,IAAA,CAAK,OAAO,CAAC,CAAA;AAAA,IAC3D;AAAA,GACF;AACF;AACO,SAAS,eAAe,IAAA,EAAsC;AACnE,EAAA,OAAO,IAAA,CAAK,SAAA,CAAU,MAAA,CAAO,IAAI,CAAC,CAAA;AACpC","file":"tron-FI2B6DRS.js","sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Secp256k1, Hex, Signature, Hash, Bytes, PublicKey } from \"ox\";\nimport { base58 } from \"@scure/base\";\n\nexport function verifyTIP191(\n address: string,\n message: string,\n proof: Hex.Hex,\n): boolean {\n try {\n const payload = getSignPayload(Hex.fromString(message));\n const signature = Signature.fromHex(proof);\n const publicKey = Secp256k1.recoverPublicKey({ payload, signature });\n const hex: Hex.Hex = `0x41${Hash.keccak256(\n `0x${PublicKey.toHex(publicKey).slice(4)}`,\n ).substring(26)}`;\n const bytes = Bytes.from(hex);\n const checksum = Bytes.from(Hash.sha256(Hash.sha256(hex))).slice(0, 4);\n const checked = Bytes.concat(bytes, checksum);\n const b58 = base58.encode(checked);\n return b58 === address;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n } catch (error) {\n return false;\n }\n}\n\nexport async function verifyPersonalSignTIP191(\n proof: SignatureProof,\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"tron\") return { ...proof, status: ProofStatus.FAILED };\n\n const verified = verifyTIP191(\n address as Hex.Hex,\n proof.attestation,\n proof.proof as Hex.Hex,\n );\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n\nexport function encode(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n const message = Hex.from(data);\n return Hex.concat(\n // Personal Sign Format: `0x19 ‖ \"Ethereum Signed Message:\\n\" ‖ message.length ‖ message`\n \"0x19\",\n Hex.fromString(\"TRON Signed Message:\\n\" + Hex.size(message)),\n message,\n );\n}\nexport function getSignPayload(data: Hex.Hex | Bytes.Bytes): Hex.Hex {\n return Hash.keccak256(encode(data));\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { ProofStatus } from '@notabene/javascript-sdk';
|
|
3
|
+
import { Keypair } from '@stellar/stellar-sdk';
|
|
4
|
+
|
|
5
|
+
if (typeof globalThis !== 'undefined' && !globalThis.Buffer) { globalThis.Buffer = Buffer; }
|
|
6
|
+
function verifyStellarSignature(proof) {
|
|
7
|
+
const [ns, , address] = proof.address.split(/:/);
|
|
8
|
+
if (ns !== "stellar") return { ...proof, status: ProofStatus.FAILED };
|
|
9
|
+
try {
|
|
10
|
+
const keypair = Keypair.fromPublicKey(address);
|
|
11
|
+
const messageBuffer = Buffer.from(proof.attestation, "utf-8");
|
|
12
|
+
const signatureBuffer = Buffer.from(proof.proof, "base64");
|
|
13
|
+
const verified = keypair.verify(messageBuffer, signatureBuffer);
|
|
14
|
+
return {
|
|
15
|
+
...proof,
|
|
16
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED
|
|
17
|
+
};
|
|
18
|
+
} catch {
|
|
19
|
+
return { ...proof, status: ProofStatus.FAILED };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { verifyStellarSignature };
|
|
24
|
+
//# sourceMappingURL=xlm-TNRZ5CFC.js.map
|
|
25
|
+
//# sourceMappingURL=xlm-TNRZ5CFC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/xlm.ts"],"names":[],"mappings":";;;;;AAGO,SAAS,uBACd,KAAA,EACgB;AAChB,EAAA,MAAM,CAAC,MAAM,OAAO,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC/C,EAAA,IAAI,EAAA,KAAO,WAAW,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAEpE,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,aAAA,CAAc,OAAO,CAAA;AAC7C,IAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,aAAa,OAAO,CAAA;AAC5D,IAAA,MAAM,eAAA,GAAkB,MAAA,CAAO,IAAA,CAAK,KAAA,CAAM,OAAO,QAAQ,CAAA;AAEzD,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,MAAA,CAAO,aAAA,EAAe,eAAe,CAAA;AAE9D,IAAA,OAAO;AAAA,MACL,GAAG,KAAA;AAAA,MACH,MAAA,EAAQ,QAAA,GAAW,WAAA,CAAY,QAAA,GAAW,WAAA,CAAY;AAAA,KACxD;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AACF","file":"xlm-TNRZ5CFC.js","sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { Keypair } from \"@stellar/stellar-sdk\";\n\nexport function verifyStellarSignature(\n proof: SignatureProof,\n): SignatureProof {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"stellar\") return { ...proof, status: ProofStatus.FAILED };\n\n try {\n const keypair = Keypair.fromPublicKey(address);\n const messageBuffer = Buffer.from(proof.attestation, \"utf-8\");\n const signatureBuffer = Buffer.from(proof.proof, \"base64\");\n\n const verified = keypair.verify(messageBuffer, signatureBuffer);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n } catch {\n return { ...proof, status: ProofStatus.FAILED };\n }\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
|
+
import { ProofStatus } from '@notabene/javascript-sdk';
|
|
3
|
+
import { Client } from 'xrpl';
|
|
4
|
+
import { verify } from 'ripple-keypairs';
|
|
5
|
+
|
|
6
|
+
if (typeof globalThis !== 'undefined' && !globalThis.Buffer) { globalThis.Buffer = Buffer; }
|
|
7
|
+
function verifyXRPL(message, publicKey, proof) {
|
|
8
|
+
return verify(Buffer.from(message).toString("hex"), proof, publicKey);
|
|
9
|
+
}
|
|
10
|
+
var xrplTestnetWs = [
|
|
11
|
+
"wss://s.altnet.rippletest.net:51233",
|
|
12
|
+
"wss://testnet.xrpl-labs.com/"
|
|
13
|
+
];
|
|
14
|
+
var xrplMainnetWs = [
|
|
15
|
+
"wss://s1.ripple.com",
|
|
16
|
+
"wss://xrplcluster.com/",
|
|
17
|
+
// full node
|
|
18
|
+
"wss://s2.ripple.com/"
|
|
19
|
+
];
|
|
20
|
+
async function getPublicKey(address, isTest) {
|
|
21
|
+
const servers = isTest ? xrplTestnetWs : xrplMainnetWs;
|
|
22
|
+
for (const server of servers) {
|
|
23
|
+
try {
|
|
24
|
+
const client = new Client(server);
|
|
25
|
+
await client.connect();
|
|
26
|
+
const response = await client.request({
|
|
27
|
+
command: "account_tx",
|
|
28
|
+
account: address,
|
|
29
|
+
binary: false,
|
|
30
|
+
limit: 2,
|
|
31
|
+
forward: false
|
|
32
|
+
});
|
|
33
|
+
await client.disconnect();
|
|
34
|
+
return getSigningPubkeyFromLatestTx(response.result?.transactions);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
let errorMessage = "Connection to XRPL server failed";
|
|
37
|
+
if (error instanceof Error) {
|
|
38
|
+
errorMessage += `: ${error.message}`;
|
|
39
|
+
}
|
|
40
|
+
console.error(errorMessage);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function getSigningPubkeyFromLatestTx(latestTx) {
|
|
45
|
+
for (let i = 0; i < latestTx.length; i++) {
|
|
46
|
+
const signingPubKey = latestTx[i]?.tx_json?.SigningPubKey ?? "0x";
|
|
47
|
+
return signingPubKey;
|
|
48
|
+
}
|
|
49
|
+
throw new Error("No valid pubkey found in the latest transactions");
|
|
50
|
+
}
|
|
51
|
+
async function verifyPersonalSignXRPL(proof, publicKey, isTest) {
|
|
52
|
+
const [ns, , address] = proof.address.split(/:/);
|
|
53
|
+
if (ns !== "xrpl") return { ...proof, status: ProofStatus.FAILED };
|
|
54
|
+
if (!publicKey) {
|
|
55
|
+
publicKey = await getPublicKey(address, isTest);
|
|
56
|
+
}
|
|
57
|
+
if (!publicKey) {
|
|
58
|
+
return { ...proof, status: ProofStatus.FAILED };
|
|
59
|
+
}
|
|
60
|
+
const verified = verifyXRPL(proof.attestation, publicKey, proof.proof);
|
|
61
|
+
return {
|
|
62
|
+
...proof,
|
|
63
|
+
status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { verifyPersonalSignXRPL, verifyXRPL, xrplMainnetWs, xrplTestnetWs };
|
|
68
|
+
//# sourceMappingURL=xrpl-52IBJ4EW.js.map
|
|
69
|
+
//# sourceMappingURL=xrpl-52IBJ4EW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/xrpl.ts"],"names":[],"mappings":";;;;;;AAIO,SAAS,UAAA,CACd,OAAA,EACA,SAAA,EACA,KAAA,EACS;AACT,EAAA,OAAO,MAAA,CAAO,OAAO,IAAA,CAAK,OAAO,EAAE,QAAA,CAAS,KAAK,CAAA,EAAG,KAAA,EAAO,SAAS,CAAA;AACtE;AAEO,IAAM,aAAA,GAAgB;AAAA,EAC3B,qCAAA;AAAA,EACA;AACF;AAEO,IAAM,aAAA,GAAgB;AAAA,EAC3B,qBAAA;AAAA,EACA,wBAAA;AAAA;AAAA,EACA;AACF;AAGA,eAAe,YAAA,CACb,SACA,MAAA,EAC6B;AAC7B,EAAA,MAAM,OAAA,GAAU,SAAS,aAAA,GAAgB,aAAA;AAEzC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,IAAI,MAAA,CAAO,MAAM,CAAA;AAChC,MAAA,MAAM,OAAO,OAAA,EAAQ;AAErB,MAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,OAAA,CAAQ;AAAA,QACpC,OAAA,EAAS,YAAA;AAAA,QACT,OAAA,EAAS,OAAA;AAAA,QACT,MAAA,EAAQ,KAAA;AAAA,QACR,KAAA,EAAO,CAAA;AAAA,QACP,OAAA,EAAS;AAAA,OACV,CAAA;AAED,MAAA,MAAM,OAAO,UAAA,EAAW;AACxB,MAAA,OAAO,4BAAA,CAA6B,QAAA,CAAS,MAAA,EAAQ,YAAY,CAAA;AAAA,IACnE,SAAS,KAAA,EAAO;AACd,MAAA,IAAI,YAAA,GAAe,kCAAA;AACnB,MAAA,IAAI,iBAAiB,KAAA,EAAO;AAC1B,QAAA,YAAA,IAAgB,CAAA,EAAA,EAAK,MAAM,OAAO,CAAA,CAAA;AAAA,MACpC;AACA,MAAA,OAAA,CAAQ,MAAM,YAAY,CAAA;AAAA,IAE5B;AAAA,EACF;AACF;AAEA,SAAS,6BACP,QAAA,EACQ;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AAExC,IAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,CAAC,CAAA,EAAG,SAAS,aAAA,IAAiB,IAAA;AAG7D,IAAA,OAAO,aAAA;AAAA,EACT;AACA,EAAA,MAAM,IAAI,MAAM,kDAAkD,CAAA;AACpE;AAEA,eAAsB,sBAAA,CACpB,KAAA,EACA,SAAA,EACA,MAAA,EACyB;AACzB,EAAA,MAAM,CAAC,MAAM,OAAO,IAAI,KAAA,CAAM,OAAA,CAAQ,MAAM,GAAG,CAAA;AAC/C,EAAA,IAAI,EAAA,KAAO,QAAQ,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAEjE,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,SAAA,GAAY,MAAM,YAAA,CAAa,OAAA,EAAS,MAAM,CAAA;AAAA,EAChD;AAEA,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OAAO,EAAE,GAAG,KAAA,EAAO,MAAA,EAAQ,YAAY,MAAA,EAAO;AAAA,EAChD;AAEA,EAAA,MAAM,WAAW,UAAA,CAAW,KAAA,CAAM,WAAA,EAAa,SAAA,EAAW,MAAM,KAAK,CAAA;AAErE,EAAA,OAAO;AAAA,IACL,GAAG,KAAA;AAAA,IACH,MAAA,EAAQ,QAAA,GAAW,WAAA,CAAY,QAAA,GAAW,WAAA,CAAY;AAAA,GACxD;AACF","file":"xrpl-52IBJ4EW.js","sourcesContent":["import { ProofStatus, SignatureProof } from \"@notabene/javascript-sdk\";\nimport { AccountTxTransaction, Client } from \"xrpl\";\nimport { verify } from \"ripple-keypairs\";\n\nexport function verifyXRPL(\n message: string,\n publicKey: string,\n proof: string\n): boolean {\n return verify(Buffer.from(message).toString(\"hex\"), proof, publicKey);\n}\n\nexport const xrplTestnetWs = [\n \"wss://s.altnet.rippletest.net:51233\",\n \"wss://testnet.xrpl-labs.com/\",\n];\n\nexport const xrplMainnetWs = [\n \"wss://s1.ripple.com\",\n \"wss://xrplcluster.com/\", // full node\n \"wss://s2.ripple.com/\",\n];\n\n// If the public key is not provided, we need to get it directly\nasync function getPublicKey(\n address: string,\n isTest?: boolean\n): Promise<string | undefined> {\n const servers = isTest ? xrplTestnetWs : xrplMainnetWs;\n\n for (const server of servers) {\n try {\n const client = new Client(server);\n await client.connect();\n\n const response = await client.request({\n command: \"account_tx\",\n account: address,\n binary: false,\n limit: 2,\n forward: false,\n });\n\n await client.disconnect();\n return getSigningPubkeyFromLatestTx(response.result?.transactions);\n } catch (error) {\n let errorMessage = \"Connection to XRPL server failed\";\n if (error instanceof Error) {\n errorMessage += `: ${error.message}`;\n }\n console.error(errorMessage);\n // Continue to next server\n }\n }\n}\n\nfunction getSigningPubkeyFromLatestTx(\n latestTx: AccountTxTransaction[]\n): string {\n for (let i = 0; i < latestTx.length; i++) {\n // Check if the Account in the .tx is the address derived from the pubkey\n const signingPubKey = latestTx[i]?.tx_json?.SigningPubKey ?? \"0x\";\n // TODO: https://github.com/Cypher-Laboratory/xrpl-publickey-getter/blob/main/src/pubKeyGetter.ts#L98\n // Check the public key matches the address properly\n return signingPubKey;\n }\n throw new Error(\"No valid pubkey found in the latest transactions\");\n}\n\nexport async function verifyPersonalSignXRPL(\n proof: SignatureProof,\n publicKey?: string,\n isTest?: boolean\n): Promise<SignatureProof> {\n const [ns, , address] = proof.address.split(/:/);\n if (ns !== \"xrpl\") return { ...proof, status: ProofStatus.FAILED };\n\n if (!publicKey) {\n publicKey = await getPublicKey(address, isTest);\n }\n\n if (!publicKey) {\n return { ...proof, status: ProofStatus.FAILED };\n }\n\n const verified = verifyXRPL(proof.attestation, publicKey, proof.proof);\n\n return {\n ...proof,\n status: verified ? ProofStatus.VERIFIED : ProofStatus.FAILED,\n };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notabene/verify-proof",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0-next.12",
|
|
4
4
|
"description": "Verify ownership proofs",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://gitlab.com/notabene/libraries/verifyproof"
|
|
8
|
+
},
|
|
5
9
|
"source": "src/index.ts",
|
|
6
10
|
"type": "module",
|
|
7
|
-
"module": "dist/index.js",
|
|
8
|
-
"types": "dist/index.d.ts",
|
|
9
|
-
"main": "dist/index.cjs",
|
|
11
|
+
"module": "dist/esm/index.js",
|
|
12
|
+
"types": "dist/esm/index.d.ts",
|
|
13
|
+
"main": "dist/cjs/index.cjs",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/esm/index.d.ts",
|
|
18
|
+
"default": "./dist/esm/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/cjs/index.d.cts",
|
|
22
|
+
"default": "./dist/cjs/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
10
26
|
"author": "Pelle Braendgaard",
|
|
11
27
|
"license": "Apache-2.0",
|
|
12
28
|
"packageManager": "yarn@4.6.0",
|
|
@@ -19,7 +35,7 @@
|
|
|
19
35
|
"scripts": {
|
|
20
36
|
"build:dev": "yarn build && yarn dev",
|
|
21
37
|
"build:clean": "rm -rf dist",
|
|
22
|
-
"build": "
|
|
38
|
+
"build": "rm -rf dist && tsup",
|
|
23
39
|
"lint": "eslint ./src",
|
|
24
40
|
"test:unit": "vitest",
|
|
25
41
|
"test:coverage": "vitest --coverage"
|
|
@@ -37,6 +53,7 @@
|
|
|
37
53
|
"microbundle": "^0.15.1",
|
|
38
54
|
"semantic-release": "^24.2.3",
|
|
39
55
|
"tronweb": "^6.0.0",
|
|
56
|
+
"tsup": "^8.0.0",
|
|
40
57
|
"typescript": "^5.5.4",
|
|
41
58
|
"typescript-eslint": "^8.24.1",
|
|
42
59
|
"vite": "^5.4.11",
|
|
@@ -46,13 +63,17 @@
|
|
|
46
63
|
"@cardano-foundation/cardano-verify-datasignature": "^1.0.11",
|
|
47
64
|
"@cosmjs/amino": "^0.34.0",
|
|
48
65
|
"@noble/curves": "^1.7.0",
|
|
66
|
+
"@noble/hashes": "^1.8.0",
|
|
49
67
|
"@notabene/javascript-sdk": "2.11.0-next.2",
|
|
50
68
|
"@scure/base": "^1.2.1",
|
|
51
69
|
"@stellar/stellar-sdk": "^13.1.0",
|
|
70
|
+
"bech32": "^2.0.0",
|
|
52
71
|
"bip322-js": "^2.0.0",
|
|
72
|
+
"buffer": "^6.0.3",
|
|
53
73
|
"ox": "^0.2.2",
|
|
74
|
+
"ripple-keypairs": "^2.0.0",
|
|
54
75
|
"tweetnacl": "^1.0.3",
|
|
55
76
|
"varuint-bitcoin": "^2.0.0",
|
|
56
77
|
"xrpl": "^4.2.5"
|
|
57
78
|
}
|
|
58
|
-
}
|
|
79
|
+
}
|
package/src/bitcoin.ts
CHANGED
|
@@ -10,6 +10,7 @@ import { Hash } from "ox";
|
|
|
10
10
|
import { secp256k1 } from "@noble/curves/secp256k1";
|
|
11
11
|
import { SignatureType } from "@noble/curves/abstract/weierstrass";
|
|
12
12
|
import { Verifier } from "bip322-js";
|
|
13
|
+
import { decodeCashAddr } from "./cashaddr";
|
|
13
14
|
|
|
14
15
|
enum SEGWIT_TYPES {
|
|
15
16
|
P2WPKH = "p2wpkh",
|
|
@@ -88,7 +89,12 @@ enum DerivationMode {
|
|
|
88
89
|
export async function verifyBTCSignature(
|
|
89
90
|
proof: SignatureProof
|
|
90
91
|
): Promise<SignatureProof> {
|
|
91
|
-
|
|
92
|
+
// Split on ":" but rejoin from index 2 onwards so that a prefixed CashAddr
|
|
93
|
+
// like "bitcoincash:qr..." in the third segment is preserved whole.
|
|
94
|
+
// e.g. "bip122:<chainId>:bitcoincash:qr..." → address = "bitcoincash:qr..."
|
|
95
|
+
const parts = proof.address.split(":");
|
|
96
|
+
const ns = parts[0];
|
|
97
|
+
const address = parts.slice(2).join(":");
|
|
92
98
|
if (ns !== "bip122") return { ...proof, status: ProofStatus.FAILED };
|
|
93
99
|
|
|
94
100
|
// Map chainId to our chain configuration
|
|
@@ -102,7 +108,11 @@ export async function verifyBTCSignature(
|
|
|
102
108
|
|
|
103
109
|
// Use BIP322 for testnet addresses
|
|
104
110
|
if (chainConfig.isTestnet) {
|
|
105
|
-
|
|
111
|
+
try {
|
|
112
|
+
return verifyBIP322(address, proof);
|
|
113
|
+
} catch {
|
|
114
|
+
return { ...proof, status: ProofStatus.FAILED };
|
|
115
|
+
}
|
|
106
116
|
}
|
|
107
117
|
|
|
108
118
|
// Check if this is a Taproot address (bc1p or tb1p)
|
|
@@ -158,11 +168,17 @@ function getChainConfig(address: string): ChainConfig {
|
|
|
158
168
|
if (address.startsWith("X") || address.startsWith("7")) {
|
|
159
169
|
return CHAIN_CONFIGS["dash"];
|
|
160
170
|
}
|
|
161
|
-
if (address.startsWith("q")) {
|
|
171
|
+
if (address.startsWith("q") || address.startsWith("bitcoincash:")) {
|
|
162
172
|
return CHAIN_CONFIGS["bitcoincash"];
|
|
163
173
|
}
|
|
164
|
-
|
|
165
|
-
|
|
174
|
+
// Bitcoin testnet addresses can start with "m", "n", "2", or "tb1"
|
|
175
|
+
if (
|
|
176
|
+
address.startsWith("m") ||
|
|
177
|
+
address.startsWith("n") ||
|
|
178
|
+
address.startsWith("2") ||
|
|
179
|
+
address.startsWith("tb1")
|
|
180
|
+
) {
|
|
181
|
+
return CHAIN_CONFIGS["testnet"]
|
|
166
182
|
}
|
|
167
183
|
|
|
168
184
|
return CHAIN_CONFIGS["bitcoin"];
|
|
@@ -220,7 +236,7 @@ function getDerivationMode(address: string) {
|
|
|
220
236
|
return DerivationMode.LEGACY;
|
|
221
237
|
} else if (address.match("^(D).*")) {
|
|
222
238
|
return DerivationMode.DOGECOIN;
|
|
223
|
-
} else if (address.match("^(q).*")) {
|
|
239
|
+
} else if (address.match("^(q).*") || address.startsWith("bitcoincash:")) {
|
|
224
240
|
return DerivationMode.BCH;
|
|
225
241
|
} else if (address.match("^(t1|t3).*")) {
|
|
226
242
|
return DerivationMode.LEGACY; // Zcash addresses
|
|
@@ -280,26 +296,34 @@ function verify(
|
|
|
280
296
|
const publicKey = signature.recoverPublicKey(hash);
|
|
281
297
|
const publicKeyBytes = publicKey.toRawBytes(compressed);
|
|
282
298
|
const publicKeyHash = hash160(publicKeyBytes);
|
|
283
|
-
let actual: string = "";
|
|
284
|
-
|
|
285
299
|
// Special handling for Bitcoin Cash addresses
|
|
286
|
-
if (address.startsWith("q")) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
if (address.startsWith("q") || address.startsWith("bitcoincash:")) {
|
|
301
|
+
try {
|
|
302
|
+
const decoded = decodeCashAddr(address);
|
|
303
|
+
if (decoded.type !== 0) return false; // Must be P2PKH
|
|
304
|
+
if (decoded.hash.length !== publicKeyHash.length) return false;
|
|
305
|
+
for (let i = 0; i < decoded.hash.length; i++) {
|
|
306
|
+
if (decoded.hash[i] !== publicKeyHash[i]) return false;
|
|
307
|
+
}
|
|
308
|
+
return true;
|
|
309
|
+
} catch {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
296
312
|
}
|
|
297
313
|
|
|
314
|
+
let actual: string = "";
|
|
315
|
+
|
|
298
316
|
if (segwitType) {
|
|
299
317
|
if (segwitType === SEGWIT_TYPES.P2SH_P2WPKH) {
|
|
318
|
+
// P2SH-P2WPKH: address is hash160 of the witness redeem script, not the raw pubkey hash
|
|
319
|
+
const redeemScript = new Uint8Array(22);
|
|
320
|
+
redeemScript[0] = 0x00; // OP_0
|
|
321
|
+
redeemScript[1] = 0x14; // push 20 bytes
|
|
322
|
+
redeemScript.set(publicKeyHash, 2);
|
|
323
|
+
const redeemScriptHash = hash160(redeemScript);
|
|
300
324
|
actual = encodeBase58AddressFormat(
|
|
301
325
|
chainConfig.scriptHashVersion,
|
|
302
|
-
|
|
326
|
+
redeemScriptHash
|
|
303
327
|
);
|
|
304
328
|
} else {
|
|
305
329
|
// parsed.segwitType === SEGWIT_TYPES.P2WPKH
|
package/src/cashaddr.ts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { bech32 } from "@scure/base";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* CashAddr base32 character set.
|
|
5
|
+
* Each character maps to its 5-bit index value (0–31).
|
|
6
|
+
* Spec: https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/cashaddr.md
|
|
7
|
+
*/
|
|
8
|
+
const CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generator polynomials for the CashAddr BCH checksum.
|
|
12
|
+
* These five constants define the GF(2^32) polynomial used to compute
|
|
13
|
+
* and validate the 40-bit checksum appended to every CashAddr string.
|
|
14
|
+
*/
|
|
15
|
+
const GENERATOR = [
|
|
16
|
+
BigInt("0x98f2bc8e61"),
|
|
17
|
+
BigInt("0x79b76d99e2"),
|
|
18
|
+
BigInt("0xf33e5fb3c4"),
|
|
19
|
+
BigInt("0xae2eabe2a8"),
|
|
20
|
+
BigInt("0x1e4f43e470"),
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Computes the CashAddr BCH checksum over an array of 5-bit values.
|
|
25
|
+
*
|
|
26
|
+
* The input should be the concatenation of:
|
|
27
|
+
* - the prefix expansion (see {@link prefixExpand})
|
|
28
|
+
* - all payload words including the 8 checksum words
|
|
29
|
+
*
|
|
30
|
+
* A valid address produces a result of `0n`; any other value indicates
|
|
31
|
+
* a corrupt or invalid address.
|
|
32
|
+
*
|
|
33
|
+
* @param values - Array of 5-bit integers covering prefix + full payload
|
|
34
|
+
* @returns The 40-bit checksum residue as a bigint (0n = valid)
|
|
35
|
+
*/
|
|
36
|
+
function polymod(values: number[]): bigint {
|
|
37
|
+
let c = BigInt(1);
|
|
38
|
+
for (const d of values) {
|
|
39
|
+
// Extract the top 5 bits before shifting
|
|
40
|
+
const c0 = c >> BigInt(35);
|
|
41
|
+
// Shift the accumulator left by 5 bits and XOR in the next data word
|
|
42
|
+
c = ((c & BigInt("0x07ffffffff")) << BigInt(5)) ^ BigInt(d);
|
|
43
|
+
// Apply each generator polynomial for set bits in c0
|
|
44
|
+
for (let i = 0; i < 5; i++) {
|
|
45
|
+
if ((c0 >> BigInt(i)) & BigInt(1)) {
|
|
46
|
+
c ^= GENERATOR[i];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Final XOR with 1 so a valid address yields 0
|
|
51
|
+
return c ^ BigInt(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Expands a CashAddr prefix into the form required by the checksum algorithm.
|
|
56
|
+
*
|
|
57
|
+
* Each character of the prefix is reduced to its lower 5 bits, then a zero
|
|
58
|
+
* byte is appended as a separator between the prefix and the payload words.
|
|
59
|
+
*
|
|
60
|
+
* @param prefix - The human-readable prefix (e.g. `"bitcoincash"`)
|
|
61
|
+
* @returns Array of 5-bit integers representing the expanded prefix
|
|
62
|
+
*/
|
|
63
|
+
function prefixExpand(prefix: string): number[] {
|
|
64
|
+
const result: number[] = [];
|
|
65
|
+
for (let i = 0; i < prefix.length; i++) {
|
|
66
|
+
// Keep only the lower 5 bits of each character's ASCII code
|
|
67
|
+
result.push(prefix.charCodeAt(i) & 0x1f);
|
|
68
|
+
}
|
|
69
|
+
// Zero separator between prefix and payload
|
|
70
|
+
result.push(0);
|
|
71
|
+
return result;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Decodes a CashAddr string into its prefix, address type, and raw hash.
|
|
76
|
+
*
|
|
77
|
+
* Supports both prefixed (`bitcoincash:q...`) and prefix-less (`q...`) forms.
|
|
78
|
+
* Validates the BCH checksum and rejects non-P2PKH types or malformed input.
|
|
79
|
+
*
|
|
80
|
+
* Address type values (upper nibble of the version byte):
|
|
81
|
+
* - `0` — P2PKH (pay-to-public-key-hash)
|
|
82
|
+
* - `1` — P2SH (pay-to-script-hash)
|
|
83
|
+
*
|
|
84
|
+
* @param address - The CashAddr string to decode
|
|
85
|
+
* @param defaultPrefix - Prefix to assume when none is present in the address (default: `"bitcoincash"`)
|
|
86
|
+
* @returns An object with:
|
|
87
|
+
* - `prefix` — the decoded human-readable prefix
|
|
88
|
+
* - `type` — the address type (0 = P2PKH, 1 = P2SH, …)
|
|
89
|
+
* - `hash` — the raw public-key or script hash bytes
|
|
90
|
+
* @throws If the address contains invalid characters, fails the checksum, has a mismatched hash length,
|
|
91
|
+
* contains mixed upper/lower case, or if the payload contains invalid 5-to-8-bit padding
|
|
92
|
+
* (thrown by {@link bech32.fromWords} from `@scure/base`)
|
|
93
|
+
*/
|
|
94
|
+
export function decodeCashAddr(
|
|
95
|
+
address: string,
|
|
96
|
+
defaultPrefix = "bitcoincash"
|
|
97
|
+
): { prefix: string; type: number; hash: Uint8Array } {
|
|
98
|
+
let prefix: string;
|
|
99
|
+
|
|
100
|
+
// Split on ":" to separate an explicit prefix from the payload
|
|
101
|
+
const colonIndex = address.indexOf(":");
|
|
102
|
+
if (colonIndex !== -1) {
|
|
103
|
+
prefix = address.slice(0, colonIndex).toLowerCase();
|
|
104
|
+
} else {
|
|
105
|
+
prefix = defaultPrefix;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// CashAddr spec forbids mixed upper/lower case
|
|
109
|
+
const rawPayload = colonIndex !== -1 ? address.slice(colonIndex + 1) : address;
|
|
110
|
+
if (/[A-Z]/.test(rawPayload) && /[a-z]/.test(rawPayload)) {
|
|
111
|
+
throw new Error("Invalid CashAddr: mixed case");
|
|
112
|
+
}
|
|
113
|
+
const payload = rawPayload.toLowerCase();
|
|
114
|
+
|
|
115
|
+
// Map each character to its 5-bit index in the CashAddr alphabet
|
|
116
|
+
const words: number[] = [];
|
|
117
|
+
for (const ch of payload) {
|
|
118
|
+
const idx = CHARSET.indexOf(ch);
|
|
119
|
+
if (idx === -1) throw new Error("Invalid CashAddr character: " + ch);
|
|
120
|
+
words.push(idx);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Minimum length: at least 1 data word + 8 checksum words
|
|
124
|
+
if (words.length < 8) throw new Error("CashAddr too short");
|
|
125
|
+
|
|
126
|
+
// Verify the BCH checksum over prefix expansion + all payload words
|
|
127
|
+
const checksumData = [...prefixExpand(prefix), ...words];
|
|
128
|
+
if (polymod(checksumData) !== BigInt(0)) {
|
|
129
|
+
throw new Error("Invalid CashAddr checksum");
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Strip the 8 trailing checksum words; the remainder encodes (version_byte || hash)
|
|
133
|
+
const dataWords = words.slice(0, -8);
|
|
134
|
+
// Convert from 5-bit words to 8-bit bytes using bech32.fromWords (equivalent to convertBits(data, 5, 8))
|
|
135
|
+
const payloadBytes = bech32.fromWords(dataWords);
|
|
136
|
+
if (payloadBytes.length === 0) {
|
|
137
|
+
throw new Error("Invalid CashAddr padding");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// The first byte is the version byte: upper nibble = type, lower 3 bits = hash size index
|
|
141
|
+
const versionByte = payloadBytes[0];
|
|
142
|
+
const type = (versionByte >> 3) & 0x0f;
|
|
143
|
+
const hashSizeBits = versionByte & 0x07;
|
|
144
|
+
|
|
145
|
+
// Look up the expected hash length in bytes from the size index
|
|
146
|
+
const expectedSizes = [20, 24, 28, 32, 40, 48, 56, 64];
|
|
147
|
+
const expectedSize = expectedSizes[hashSizeBits];
|
|
148
|
+
|
|
149
|
+
const hashBytes = payloadBytes.slice(1);
|
|
150
|
+
if (hashBytes.length !== expectedSize) {
|
|
151
|
+
throw new Error(
|
|
152
|
+
`Hash length mismatch: expected ${expectedSize}, got ${hashBytes.length}`
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { prefix, type, hash: Uint8Array.from(hashBytes) };
|
|
157
|
+
}
|