@rango-dev/provider-noir-wallet 0.0.0-experimental-99f1781b-20260920

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/CHANGELOG.md ADDED
@@ -0,0 +1,21 @@
1
+ ## [0.3.1](https://github.com/rango-exchange/rango-client/compare/provider-noir-wallet@0.3.0...provider-noir-wallet@0.3.1) (2026-09-16)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * ship dist and changelog when publishing with npm ([0a8bd5d](https://github.com/rango-exchange/rango-client/commit/0a8bd5d779bd652b6ca7195cda4ce465ba196f0e))
7
+ # [0.3.0](https://github.com/rango-exchange/rango-client/compare/provider-noir-wallet@0.2.0...provider-noir-wallet@0.3.0) (2026-09-15)
8
+
9
+
10
+ ### Features
11
+
12
+ * add support for ledger wallet ([eacfd0b](https://github.com/rango-exchange/rango-client/commit/eacfd0bd32f87629e6cc9f6170368e1e208a6bd0))
13
+ # 0.2.0 (2026-08-18)
14
+
15
+
16
+ ### Features
17
+
18
+ * integrate noir wallet ([5e6a7da](https://github.com/rango-exchange/rango-client/commit/5e6a7da674c84df5f4fb82c4f6b5dc66bac39100))
19
+
20
+
21
+
@@ -0,0 +1,5 @@
1
+ import { type UtxoActions } from '@hub3js/bip122';
2
+ import { ChangeAccountSubscriberBuilder } from '@hub3js/std/hooks';
3
+ import { type NoirWalletProvider } from '@noir-wallet/sdk';
4
+ export declare const changeAccountSubscriberBuilder: () => ChangeAccountSubscriberBuilder<import("@noir-wallet/sdk").ZcashAddress | null, NoirWalletProvider, UtxoActions>;
5
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/builders/utxo.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8B,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,8BAA8B,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,KAAK,kBAAkB,EAAqB,MAAM,kBAAkB,CAAC;AAI9E,eAAO,MAAM,8BAA8B,uHA0B1C,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ProviderMetadata } from '@hub3js/core';
2
+ export declare const WALLET_ID = "noir-wallet";
3
+ export declare const info: ProviderMetadata;
4
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AASrD,eAAO,MAAM,SAAS,gBAAgB,CAAC;AAEvC,eAAO,MAAM,IAAI,EAAE,gBA4BlB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Noir reports a rejected connect request only in the error message, so the
3
+ * standard rejection code is attached here.
4
+ */
5
+ declare function convertNoirRejectionError(_context: unknown, error: unknown): unknown;
6
+ export declare const utxoHooks: {
7
+ convertNoirRejectionError: typeof convertNoirRejectionError;
8
+ };
9
+ export {};
10
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/hooks/utxo.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,iBAAS,yBAAyB,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAO7E;AAED,eAAO,MAAM,SAAS;;CAAgC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utxo.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.test.d.ts","sourceRoot":"","sources":["../../src/hooks/utxo.test.ts"],"names":[],"mappings":""}
package/dist/mod.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ declare const versions: () => readonly [readonly ["1.0.0", import("@hub3js/core").Provider<Record<"utxo", import("@hub3js/bip122").UtxoActions>>]];
2
+ export { versions };
3
+ export { WALLET_ID } from './constants.js';
4
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../src/mod.ts"],"names":[],"mappings":"AAIA,QAAA,MAAM,QAAQ,4HAC8C,CAAC;AAE7D,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
package/dist/mod.js ADDED
@@ -0,0 +1,2 @@
1
+ var y=Object.defineProperty;var n=(o,t)=>y(o,"name",{value:t,configurable:!0});import{defineVersions as Y}from"@hub3js/core/utils";import{ProviderBuilder as J}from"@hub3js/core";import{isNoirWalletInstalled as q}from"@noir-wallet/sdk";import{CAIP_ZCASH_CHAIN_ID as P,isChainSupported as R}from"@hub3js/bip122";import{DefaultSignerFactory as N,TransactionType as v}from"rango-types";import{isZcashBlockchain as _}from"@rango-dev/internal-blockchains";import{BigNumber as W}from"bignumber.js";import{SignerError as m,SignerErrorCode as l}from"rango-types";import{getNoirWallet as I}from"@noir-wallet/sdk";var e=n(()=>{let o=I();if(!o)throw new Error("Noir Wallet not installed");return o},"getInstanceOrThrow");var a=class{static{n(this,"CustomUtxoSigner")}async signMessage(t){return(await e().zcash.signMessage(t)).signature}async signAndSendTx(t){let{memo:r,recipientAddress:s,amount:p,decimals:S,blockChain:T}=t;if(!_(T))throw new Error(`You can not sign ${t.blockChain} using ZCash signer.`);if(r)throw new m(l.UNEXPECTED_BEHAVIOUR,"Noir Wallet can not attach a protocol memo (OP_RETURN) to a Zcash transaction.",void 0);let x=new W(p).shiftedBy(-S).toFixed();try{return{hash:await e().zcash.sendTransaction({to:s,amount:x,fundingSource:"transparent"})}}catch(c){throw typeof c=="string"?new m(l.UNEXPECTED_BEHAVIOUR,c,void 0):new m(l.SEND_TX_ERROR,void 0,c)}}};async function u(){let o=new N;return o.registerSigner(v.TRANSFER,new a),o}n(u,"getSigners");var i="noir-wallet",d={name:"Noir Wallet",icon:"https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/noir-wallet/icon.svg",extensions:{chrome:"https://chromewebstore.google.com/detail/noir-wallet/mfoghjbpfanobmnoemoepenjjcmfpmdn",homepage:"https://www.zknoir.com/"},properties:[{name:"namespaces",value:{selection:"multiple",data:[{label:"Zcash",value:"UTXO",id:"ZCASH",isChainSupported:R([P])}]}},{name:"signers",value:{getSigners:async()=>u()}}]};import{builders as L,CAIP_ZCASH_CHAIN_ID as g,utils as A}from"@hub3js/bip122";import{ActionBuilder as Z,NamespaceBuilder as j}from"@hub3js/core";import{UTXO_NAMESPACE as k}from"@hub3js/namespaces";import*as w from"@hub3js/std/builders";import{throwWalletConnectionError as M}from"@hub3js/std/operators";import{CAIP_ZCASH_CHAIN_ID as z,utils as U}from"@hub3js/bip122";import{ChangeAccountSubscriberBuilder as O}from"@hub3js/std/hooks";import"@noir-wallet/sdk";var f=n(()=>new O().getInstance(e).onSwitchAccount((o,t)=>{if(!o.payload?.transparent){t.action("disconnect"),o.preventDefault();return}}).format(async(o,t)=>U.formatAccountsToCAIP(t?.transparent?[t.transparent]:[],z)).addEventListener((o,t)=>{o.zcash.on("accountsChanged",t)}).removeEventListener((o,t)=>{o.zcash.removeListener("accountsChanged",t)}),"changeAccountSubscriberBuilder");import{USER_REJECTION_ERROR_CODE as B}from"@hub3js/std/utils";var D="User rejected the request";function H(o,t){return t instanceof Error&&t.message===D?Object.assign(new Error(t.message),{code:B}):t}n(H,"convertNoirRejectionError");var h={convertNoirRejectionError:H};var[X,E]=f().build(),F=L.connect().action(async function(){let t=e().zcash,r=await t.getAccounts();if(!r){let s=await t.connect();return A.formatAccountsToCAIP([s.transparent],g)}return A.formatAccountsToCAIP([r.transparent],g)}).before(X).or(E).or(h.convertNoirRejectionError).or(M(k)).build(),G=new Z("canEagerConnect").action(async()=>{try{return!!await e().zcash.getAccounts()}catch{return!1}}).build(),V=w.disconnect().before(()=>{try{e().zcash.disconnect()}catch{}}).after(E).build(),C=new j("UTXO",i).action(F).action(V).action(G).build();var b=n(()=>new J(i).init(function(o){let[,t]=o.state();q()&&(t("installed",!0),console.debug("[noir-wallet] instance detected.",o))}).config("metadata",d).add("utxo",C).build(),"buildProvider");var kt=n(()=>Y().version("1.0.0",b()).build(),"versions");export{i as WALLET_ID,kt as versions};
2
+ //# sourceMappingURL=mod.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/mod.ts", "../src/provider.ts", "../src/constants.ts", "../src/signer.ts", "../src/signers/signer.ts", "../src/utils.ts", "../src/namespaces/utxo.ts", "../src/builders/utxo.ts", "../src/hooks/utxo.ts"],
4
+ "sourcesContent": ["import { defineVersions } from '@hub3js/core/utils';\n\nimport { buildProvider } from './provider.js';\n\nconst versions = () =>\n defineVersions().version('1.0.0', buildProvider()).build();\n\nexport { versions };\nexport { WALLET_ID } from './constants.js';\n", "import { ProviderBuilder } from '@hub3js/core';\nimport { isNoirWalletInstalled } from '@noir-wallet/sdk';\n\nimport { info, WALLET_ID } from './constants.js';\nimport { namespace as utxo } from './namespaces/utxo.js';\n\nconst buildProvider = () =>\n new ProviderBuilder(WALLET_ID)\n .init(function (context) {\n const [, setState] = context.state();\n if (isNoirWalletInstalled()) {\n setState('installed', true);\n console.debug('[noir-wallet] instance detected.', context);\n }\n })\n .config('metadata', info)\n .add('utxo', utxo)\n .build();\n\nexport { buildProvider };\n", "import type { ProviderMetadata } from '@hub3js/core';\n\nimport {\n CAIP_ZCASH_CHAIN_ID,\n isChainSupported as isBip122ChainSupported,\n} from '@hub3js/bip122';\n\nimport getSigners from './signer.js';\n\nexport const WALLET_ID = 'noir-wallet';\n\nexport const info: ProviderMetadata = {\n name: 'Noir Wallet',\n icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/noir-wallet/icon.svg',\n extensions: {\n chrome:\n 'https://chromewebstore.google.com/detail/noir-wallet/mfoghjbpfanobmnoemoepenjjcmfpmdn',\n homepage: 'https://www.zknoir.com/',\n },\n properties: [\n {\n name: 'namespaces',\n value: {\n selection: 'multiple',\n data: [\n {\n label: 'Zcash',\n value: 'UTXO',\n id: 'ZCASH',\n isChainSupported: isBip122ChainSupported([CAIP_ZCASH_CHAIN_ID]),\n },\n ],\n },\n },\n {\n name: 'signers',\n value: { getSigners: async () => getSigners() },\n },\n ],\n};\n", "import type { SignerFactory } from 'rango-types';\n\nimport { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';\n\nimport { CustomUtxoSigner } from './signers/signer.js';\n\nexport default async function getSigners(): Promise<SignerFactory> {\n const signers = new DefaultSignerFactory();\n\n signers.registerSigner(TxType.TRANSFER, new CustomUtxoSigner());\n return signers;\n}\n", "import type { Transfer } from 'rango-types/mainApi';\n\nimport { isZcashBlockchain } from '@rango-dev/internal-blockchains';\nimport { BigNumber } from 'bignumber.js';\nimport { type GenericSigner, SignerError, SignerErrorCode } from 'rango-types';\n\nimport { getInstanceOrThrow } from '../utils.js';\n\nexport class CustomUtxoSigner implements GenericSigner<Transfer> {\n async signMessage(msg: string): Promise<string> {\n const noirWallet = getInstanceOrThrow();\n const zcash = noirWallet.zcash;\n\n const result = await zcash.signMessage(msg);\n return result.signature;\n }\n\n async signAndSendTx(tx: Transfer): Promise<{ hash: string }> {\n const { memo, recipientAddress, amount, decimals, blockChain } = tx;\n\n if (!isZcashBlockchain(blockChain)) {\n throw new Error(`You can not sign ${tx.blockChain} using ZCash signer.`);\n }\n\n if (memo) {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n 'Noir Wallet can not attach a protocol memo (OP_RETURN) to a Zcash transaction.',\n undefined\n );\n }\n\n /*\n * Rango provides `amount` in the asset's smallest unit (zatoshis), but the\n * Noir Wallet expects a decimal ZEC string. Shift by `-decimals` to convert\n * (e.g. \"1000000\" zatoshis -> \"0.01\" ZEC).\n */\n const amountInZec = new BigNumber(amount).shiftedBy(-decimals).toFixed();\n\n try {\n const noirWallet = getInstanceOrThrow();\n const zcash = noirWallet.zcash;\n\n const txid = await zcash.sendTransaction({\n to: recipientAddress,\n amount: amountInZec,\n fundingSource: 'transparent',\n });\n return { hash: txid };\n } catch (error) {\n if (typeof error === 'string') {\n throw new SignerError(\n SignerErrorCode.UNEXPECTED_BEHAVIOUR,\n error,\n undefined\n );\n }\n throw new SignerError(SignerErrorCode.SEND_TX_ERROR, undefined, error);\n }\n }\n}\n", "import { getNoirWallet } from '@noir-wallet/sdk';\n\nexport const getInstanceOrThrow = () => {\n const noirWallet = getNoirWallet();\n if (!noirWallet) {\n throw new Error('Noir Wallet not installed');\n }\n return noirWallet;\n};\n", "import type { UtxoActions } from '@hub3js/bip122';\n\nimport { builders, CAIP_ZCASH_CHAIN_ID, utils } from '@hub3js/bip122';\nimport { ActionBuilder, NamespaceBuilder } from '@hub3js/core';\nimport { UTXO_NAMESPACE } from '@hub3js/namespaces';\nimport * as commonBuilders from '@hub3js/std/builders';\nimport { throwWalletConnectionError } from '@hub3js/std/operators';\n\nimport { changeAccountSubscriberBuilder } from '../builders/utxo.js';\nimport { WALLET_ID } from '../constants.js';\nimport { utxoHooks } from '../hooks/utxo.js';\nimport { getInstanceOrThrow } from '../utils.js';\n\nconst [changeAccountSubscriber, changeAccountCleanup] =\n changeAccountSubscriberBuilder().build();\n\nconst connect = builders\n .connect()\n .action(async function () {\n const noirWallet = getInstanceOrThrow();\n const zcash = noirWallet.zcash;\n\n // Check existing connection (silent, no popup)\n const accounts = await zcash.getAccounts();\n\n // Connect wallet if not connected (shows popup)\n if (!accounts) {\n const newAccounts = await zcash.connect();\n return utils.formatAccountsToCAIP(\n [newAccounts.transparent],\n CAIP_ZCASH_CHAIN_ID\n );\n }\n return utils.formatAccountsToCAIP(\n [accounts.transparent],\n CAIP_ZCASH_CHAIN_ID\n );\n })\n .before(changeAccountSubscriber)\n .or(changeAccountCleanup)\n .or(utxoHooks.convertNoirRejectionError)\n .or(throwWalletConnectionError(UTXO_NAMESPACE))\n .build();\n\nconst canEagerConnect = new ActionBuilder<UtxoActions, 'canEagerConnect'>(\n 'canEagerConnect'\n)\n .action(async () => {\n try {\n const noirWallet = getInstanceOrThrow();\n const zcash = noirWallet.zcash;\n\n // Check existing connection (silent, no popup)\n const accounts = await zcash.getAccounts();\n\n return !!accounts;\n } catch {\n return false;\n }\n })\n .build();\n\nconst disconnect = commonBuilders\n .disconnect<UtxoActions>()\n .before(() => {\n try {\n const noirWallet = getInstanceOrThrow();\n const zcash = noirWallet.zcash;\n void zcash.disconnect();\n } catch {\n // Ignore errors during disconnect\n }\n })\n .after(changeAccountCleanup)\n .build();\n\nexport const namespace = new NamespaceBuilder<UtxoActions>('UTXO', WALLET_ID)\n .action(connect)\n .action(disconnect)\n .action(canEagerConnect)\n .build();\n", "import { CAIP_ZCASH_CHAIN_ID, utils, type UtxoActions } from '@hub3js/bip122';\nimport { ChangeAccountSubscriberBuilder } from '@hub3js/std/hooks';\nimport { type NoirWalletProvider, type ZcashAccount } from '@noir-wallet/sdk';\n\nimport { getInstanceOrThrow } from '../utils.js';\n\nexport const changeAccountSubscriberBuilder = () => {\n return new ChangeAccountSubscriberBuilder<\n ZcashAccount['addresses'] | null,\n NoirWalletProvider,\n UtxoActions\n >()\n .getInstance(getInstanceOrThrow)\n .onSwitchAccount((event, context) => {\n if (!event.payload?.transparent) {\n void context.action('disconnect');\n event.preventDefault();\n return;\n }\n })\n .format(async (_, payload) =>\n utils.formatAccountsToCAIP(\n payload?.transparent ? [payload.transparent] : [],\n CAIP_ZCASH_CHAIN_ID\n )\n )\n .addEventListener((instance, callback) => {\n instance.zcash.on('accountsChanged', callback);\n })\n .removeEventListener((instance, callback) => {\n instance.zcash.removeListener('accountsChanged', callback);\n });\n};\n", "import { USER_REJECTION_ERROR_CODE } from '@hub3js/std/utils';\n\nconst USER_REJECTION_MESSAGE = 'User rejected the request';\n\n/**\n * Noir reports a rejected connect request only in the error message, so the\n * standard rejection code is attached here.\n */\nfunction convertNoirRejectionError(_context: unknown, error: unknown): unknown {\n if (error instanceof Error && error.message === USER_REJECTION_MESSAGE) {\n return Object.assign(new Error(error.message), {\n code: USER_REJECTION_ERROR_CODE,\n });\n }\n return error;\n}\n\nexport const utxoHooks = { convertNoirRejectionError };\n"],
5
+ "mappings": "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",
6
+ "names": ["defineVersions", "ProviderBuilder", "isNoirWalletInstalled", "CAIP_ZCASH_CHAIN_ID", "isBip122ChainSupported", "DefaultSignerFactory", "TxType", "isZcashBlockchain", "BigNumber", "SignerError", "SignerErrorCode", "getNoirWallet", "getInstanceOrThrow", "__name", "noirWallet", "getNoirWallet", "CustomUtxoSigner", "__name", "msg", "getInstanceOrThrow", "tx", "memo", "recipientAddress", "amount", "decimals", "blockChain", "isZcashBlockchain", "SignerError", "SignerErrorCode", "amountInZec", "BigNumber", "error", "getSigners", "signers", "DefaultSignerFactory", "TxType", "CustomUtxoSigner", "__name", "WALLET_ID", "info", "isBip122ChainSupported", "CAIP_ZCASH_CHAIN_ID", "getSigners", "builders", "CAIP_ZCASH_CHAIN_ID", "utils", "ActionBuilder", "NamespaceBuilder", "UTXO_NAMESPACE", "commonBuilders", "throwWalletConnectionError", "CAIP_ZCASH_CHAIN_ID", "utils", "ChangeAccountSubscriberBuilder", "changeAccountSubscriberBuilder", "__name", "ChangeAccountSubscriberBuilder", "getInstanceOrThrow", "event", "context", "_", "payload", "utils", "CAIP_ZCASH_CHAIN_ID", "instance", "callback", "USER_REJECTION_ERROR_CODE", "USER_REJECTION_MESSAGE", "convertNoirRejectionError", "_context", "error", "USER_REJECTION_ERROR_CODE", "__name", "utxoHooks", "changeAccountSubscriber", "changeAccountCleanup", "changeAccountSubscriberBuilder", "connect", "builders", "zcash", "getInstanceOrThrow", "accounts", "newAccounts", "utils", "CAIP_ZCASH_CHAIN_ID", "utxoHooks", "throwWalletConnectionError", "UTXO_NAMESPACE", "canEagerConnect", "ActionBuilder", "disconnect", "namespace", "NamespaceBuilder", "WALLET_ID", "buildProvider", "__name", "ProviderBuilder", "WALLET_ID", "context", "setState", "isNoirWalletInstalled", "info", "namespace", "versions", "__name", "defineVersions", "buildProvider"]
7
+ }
@@ -0,0 +1,3 @@
1
+ import type { UtxoActions } from '@hub3js/bip122';
2
+ export declare const namespace: import("@hub3js/core").ProxiedNamespace<UtxoActions>;
3
+ //# sourceMappingURL=utxo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utxo.d.ts","sourceRoot":"","sources":["../../src/namespaces/utxo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AA4ElD,eAAO,MAAM,SAAS,sDAIZ,CAAC"}
@@ -0,0 +1,3 @@
1
+ declare const buildProvider: () => import("@hub3js/core").Provider<Record<"utxo", import("@hub3js/bip122").UtxoActions>>;
2
+ export { buildProvider };
3
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,aAAa,6FAWP,CAAC;AAEb,OAAO,EAAE,aAAa,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { SignerFactory } from 'rango-types';
2
+ export default function getSigners(): Promise<SignerFactory>;
3
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMjD,wBAA8B,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAKjE"}
@@ -0,0 +1,9 @@
1
+ import type { Transfer } from 'rango-types/mainApi';
2
+ import { type GenericSigner } from 'rango-types';
3
+ export declare class CustomUtxoSigner implements GenericSigner<Transfer> {
4
+ signMessage(msg: string): Promise<string>;
5
+ signAndSendTx(tx: Transfer): Promise<{
6
+ hash: string;
7
+ }>;
8
+ }
9
+ //# sourceMappingURL=signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/signers/signer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAIpD,OAAO,EAAE,KAAK,aAAa,EAAgC,MAAM,aAAa,CAAC;AAI/E,qBAAa,gBAAiB,YAAW,aAAa,CAAC,QAAQ,CAAC;IACxD,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzC,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CA2C7D"}
@@ -0,0 +1,2 @@
1
+ export declare const getInstanceOrThrow: () => import("@noir-wallet/sdk").NoirWalletProvider;
2
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,kBAAkB,qDAM9B,CAAC"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@rango-dev/provider-noir-wallet",
3
+ "version": "0.0.0-experimental-99f1781b-20260920",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "source": "./src/mod.ts",
7
+ "main": "./dist/mod.js",
8
+ "exports": {
9
+ ".": "./dist/mod.js"
10
+ },
11
+ "typings": "dist/mod.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "src",
15
+ "CHANGELOG.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "yarn run rangutopia library build",
19
+ "ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json",
20
+ "clean": "rimraf dist",
21
+ "format": "prettier --write '{.,src}/**/*.{ts,tsx}'",
22
+ "lint": "eslint \"**/*.{ts,tsx}\""
23
+ },
24
+ "dependencies": {
25
+ "@hub3js/bip122": "0.0.0-experimental-b57d9319-20260919",
26
+ "@hub3js/core": "0.0.0-experimental-b57d9319-20260919",
27
+ "@hub3js/namespaces": "0.0.0-experimental-b57d9319-20260919",
28
+ "@hub3js/std": "0.0.0-experimental-b57d9319-20260919",
29
+ "@noir-wallet/sdk": "^0.1.9",
30
+ "@rango-dev/internal-blockchains": "^0.0.0-experimental-99f1781b-20260920",
31
+ "@rango-dev/wallets-core": "^0.0.0-experimental-99f1781b-20260920",
32
+ "bignumber.js": "^9.1.1",
33
+ "rango-types": "^0.5.0"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ }
38
+ }
package/readme.md ADDED
@@ -0,0 +1,28 @@
1
+ # Noir Wallet Provider
2
+
3
+ Noir Wallet integration for hub.
4
+ [Homepage](https://www.zknoir.com/) | [Docs](https://github.com/NoirWallet/noir-wallet-sdk)
5
+
6
+ More about implementation status can be found [here](../readme.md).
7
+
8
+ ## Implementation notes/limitation
9
+
10
+ ### Group
11
+
12
+ #### ⚠️ UTXO
13
+
14
+ Only supports Zcash.
15
+
16
+ ### Feature
17
+
18
+ #### ⚠️ Sign transaction
19
+
20
+ It only supports Zcash transparent transactions.
21
+
22
+ #### ⚠️ Switch Account
23
+
24
+ The wallet emits an empty array as switch account event when it gets locked and the namespace gets disconnected.
25
+
26
+ ---
27
+
28
+ More wallet information can be found in [readme.md](../readme.md).
@@ -0,0 +1,33 @@
1
+ import { CAIP_ZCASH_CHAIN_ID, utils, type UtxoActions } from '@hub3js/bip122';
2
+ import { ChangeAccountSubscriberBuilder } from '@hub3js/std/hooks';
3
+ import { type NoirWalletProvider, type ZcashAccount } from '@noir-wallet/sdk';
4
+
5
+ import { getInstanceOrThrow } from '../utils.js';
6
+
7
+ export const changeAccountSubscriberBuilder = () => {
8
+ return new ChangeAccountSubscriberBuilder<
9
+ ZcashAccount['addresses'] | null,
10
+ NoirWalletProvider,
11
+ UtxoActions
12
+ >()
13
+ .getInstance(getInstanceOrThrow)
14
+ .onSwitchAccount((event, context) => {
15
+ if (!event.payload?.transparent) {
16
+ void context.action('disconnect');
17
+ event.preventDefault();
18
+ return;
19
+ }
20
+ })
21
+ .format(async (_, payload) =>
22
+ utils.formatAccountsToCAIP(
23
+ payload?.transparent ? [payload.transparent] : [],
24
+ CAIP_ZCASH_CHAIN_ID
25
+ )
26
+ )
27
+ .addEventListener((instance, callback) => {
28
+ instance.zcash.on('accountsChanged', callback);
29
+ })
30
+ .removeEventListener((instance, callback) => {
31
+ instance.zcash.removeListener('accountsChanged', callback);
32
+ });
33
+ };
@@ -0,0 +1,40 @@
1
+ import type { ProviderMetadata } from '@hub3js/core';
2
+
3
+ import {
4
+ CAIP_ZCASH_CHAIN_ID,
5
+ isChainSupported as isBip122ChainSupported,
6
+ } from '@hub3js/bip122';
7
+
8
+ import getSigners from './signer.js';
9
+
10
+ export const WALLET_ID = 'noir-wallet';
11
+
12
+ export const info: ProviderMetadata = {
13
+ name: 'Noir Wallet',
14
+ icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/noir-wallet/icon.svg',
15
+ extensions: {
16
+ chrome:
17
+ 'https://chromewebstore.google.com/detail/noir-wallet/mfoghjbpfanobmnoemoepenjjcmfpmdn',
18
+ homepage: 'https://www.zknoir.com/',
19
+ },
20
+ properties: [
21
+ {
22
+ name: 'namespaces',
23
+ value: {
24
+ selection: 'multiple',
25
+ data: [
26
+ {
27
+ label: 'Zcash',
28
+ value: 'UTXO',
29
+ id: 'ZCASH',
30
+ isChainSupported: isBip122ChainSupported([CAIP_ZCASH_CHAIN_ID]),
31
+ },
32
+ ],
33
+ },
34
+ },
35
+ {
36
+ name: 'signers',
37
+ value: { getSigners: async () => getSigners() },
38
+ },
39
+ ],
40
+ };
@@ -0,0 +1,25 @@
1
+ import { USER_REJECTION_ERROR_CODE } from '@hub3js/std/utils';
2
+ import { describe, expect, it } from 'vitest';
3
+
4
+ import { utxoHooks } from './utxo.js';
5
+
6
+ const { convertNoirRejectionError } = utxoHooks;
7
+
8
+ describe('convertNoirRejectionError', () => {
9
+ it('convert a rejected request to a user rejection and keep the message', () => {
10
+ const converted = convertNoirRejectionError(
11
+ undefined,
12
+ new Error('User rejected the request')
13
+ );
14
+
15
+ expect(converted).toBeInstanceOf(Error);
16
+ expect(converted).toHaveProperty('message', 'User rejected the request');
17
+ expect(converted).toHaveProperty('code', USER_REJECTION_ERROR_CODE);
18
+ });
19
+
20
+ it('return unrecognised errors unchanged', () => {
21
+ const error = new Error('Something went wrong.');
22
+
23
+ expect(convertNoirRejectionError(undefined, error)).toBe(error);
24
+ });
25
+ });
@@ -0,0 +1,18 @@
1
+ import { USER_REJECTION_ERROR_CODE } from '@hub3js/std/utils';
2
+
3
+ const USER_REJECTION_MESSAGE = 'User rejected the request';
4
+
5
+ /**
6
+ * Noir reports a rejected connect request only in the error message, so the
7
+ * standard rejection code is attached here.
8
+ */
9
+ function convertNoirRejectionError(_context: unknown, error: unknown): unknown {
10
+ if (error instanceof Error && error.message === USER_REJECTION_MESSAGE) {
11
+ return Object.assign(new Error(error.message), {
12
+ code: USER_REJECTION_ERROR_CODE,
13
+ });
14
+ }
15
+ return error;
16
+ }
17
+
18
+ export const utxoHooks = { convertNoirRejectionError };
package/src/mod.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { defineVersions } from '@hub3js/core/utils';
2
+
3
+ import { buildProvider } from './provider.js';
4
+
5
+ const versions = () =>
6
+ defineVersions().version('1.0.0', buildProvider()).build();
7
+
8
+ export { versions };
9
+ export { WALLET_ID } from './constants.js';
@@ -0,0 +1,81 @@
1
+ import type { UtxoActions } from '@hub3js/bip122';
2
+
3
+ import { builders, CAIP_ZCASH_CHAIN_ID, utils } from '@hub3js/bip122';
4
+ import { ActionBuilder, NamespaceBuilder } from '@hub3js/core';
5
+ import { UTXO_NAMESPACE } from '@hub3js/namespaces';
6
+ import * as commonBuilders from '@hub3js/std/builders';
7
+ import { throwWalletConnectionError } from '@hub3js/std/operators';
8
+
9
+ import { changeAccountSubscriberBuilder } from '../builders/utxo.js';
10
+ import { WALLET_ID } from '../constants.js';
11
+ import { utxoHooks } from '../hooks/utxo.js';
12
+ import { getInstanceOrThrow } from '../utils.js';
13
+
14
+ const [changeAccountSubscriber, changeAccountCleanup] =
15
+ changeAccountSubscriberBuilder().build();
16
+
17
+ const connect = builders
18
+ .connect()
19
+ .action(async function () {
20
+ const noirWallet = getInstanceOrThrow();
21
+ const zcash = noirWallet.zcash;
22
+
23
+ // Check existing connection (silent, no popup)
24
+ const accounts = await zcash.getAccounts();
25
+
26
+ // Connect wallet if not connected (shows popup)
27
+ if (!accounts) {
28
+ const newAccounts = await zcash.connect();
29
+ return utils.formatAccountsToCAIP(
30
+ [newAccounts.transparent],
31
+ CAIP_ZCASH_CHAIN_ID
32
+ );
33
+ }
34
+ return utils.formatAccountsToCAIP(
35
+ [accounts.transparent],
36
+ CAIP_ZCASH_CHAIN_ID
37
+ );
38
+ })
39
+ .before(changeAccountSubscriber)
40
+ .or(changeAccountCleanup)
41
+ .or(utxoHooks.convertNoirRejectionError)
42
+ .or(throwWalletConnectionError(UTXO_NAMESPACE))
43
+ .build();
44
+
45
+ const canEagerConnect = new ActionBuilder<UtxoActions, 'canEagerConnect'>(
46
+ 'canEagerConnect'
47
+ )
48
+ .action(async () => {
49
+ try {
50
+ const noirWallet = getInstanceOrThrow();
51
+ const zcash = noirWallet.zcash;
52
+
53
+ // Check existing connection (silent, no popup)
54
+ const accounts = await zcash.getAccounts();
55
+
56
+ return !!accounts;
57
+ } catch {
58
+ return false;
59
+ }
60
+ })
61
+ .build();
62
+
63
+ const disconnect = commonBuilders
64
+ .disconnect<UtxoActions>()
65
+ .before(() => {
66
+ try {
67
+ const noirWallet = getInstanceOrThrow();
68
+ const zcash = noirWallet.zcash;
69
+ void zcash.disconnect();
70
+ } catch {
71
+ // Ignore errors during disconnect
72
+ }
73
+ })
74
+ .after(changeAccountCleanup)
75
+ .build();
76
+
77
+ export const namespace = new NamespaceBuilder<UtxoActions>('UTXO', WALLET_ID)
78
+ .action(connect)
79
+ .action(disconnect)
80
+ .action(canEagerConnect)
81
+ .build();
@@ -0,0 +1,20 @@
1
+ import { ProviderBuilder } from '@hub3js/core';
2
+ import { isNoirWalletInstalled } from '@noir-wallet/sdk';
3
+
4
+ import { info, WALLET_ID } from './constants.js';
5
+ import { namespace as utxo } from './namespaces/utxo.js';
6
+
7
+ const buildProvider = () =>
8
+ new ProviderBuilder(WALLET_ID)
9
+ .init(function (context) {
10
+ const [, setState] = context.state();
11
+ if (isNoirWalletInstalled()) {
12
+ setState('installed', true);
13
+ console.debug('[noir-wallet] instance detected.', context);
14
+ }
15
+ })
16
+ .config('metadata', info)
17
+ .add('utxo', utxo)
18
+ .build();
19
+
20
+ export { buildProvider };
package/src/signer.ts ADDED
@@ -0,0 +1,12 @@
1
+ import type { SignerFactory } from 'rango-types';
2
+
3
+ import { DefaultSignerFactory, TransactionType as TxType } from 'rango-types';
4
+
5
+ import { CustomUtxoSigner } from './signers/signer.js';
6
+
7
+ export default async function getSigners(): Promise<SignerFactory> {
8
+ const signers = new DefaultSignerFactory();
9
+
10
+ signers.registerSigner(TxType.TRANSFER, new CustomUtxoSigner());
11
+ return signers;
12
+ }
@@ -0,0 +1,61 @@
1
+ import type { Transfer } from 'rango-types/mainApi';
2
+
3
+ import { isZcashBlockchain } from '@rango-dev/internal-blockchains';
4
+ import { BigNumber } from 'bignumber.js';
5
+ import { type GenericSigner, SignerError, SignerErrorCode } from 'rango-types';
6
+
7
+ import { getInstanceOrThrow } from '../utils.js';
8
+
9
+ export class CustomUtxoSigner implements GenericSigner<Transfer> {
10
+ async signMessage(msg: string): Promise<string> {
11
+ const noirWallet = getInstanceOrThrow();
12
+ const zcash = noirWallet.zcash;
13
+
14
+ const result = await zcash.signMessage(msg);
15
+ return result.signature;
16
+ }
17
+
18
+ async signAndSendTx(tx: Transfer): Promise<{ hash: string }> {
19
+ const { memo, recipientAddress, amount, decimals, blockChain } = tx;
20
+
21
+ if (!isZcashBlockchain(blockChain)) {
22
+ throw new Error(`You can not sign ${tx.blockChain} using ZCash signer.`);
23
+ }
24
+
25
+ if (memo) {
26
+ throw new SignerError(
27
+ SignerErrorCode.UNEXPECTED_BEHAVIOUR,
28
+ 'Noir Wallet can not attach a protocol memo (OP_RETURN) to a Zcash transaction.',
29
+ undefined
30
+ );
31
+ }
32
+
33
+ /*
34
+ * Rango provides `amount` in the asset's smallest unit (zatoshis), but the
35
+ * Noir Wallet expects a decimal ZEC string. Shift by `-decimals` to convert
36
+ * (e.g. "1000000" zatoshis -> "0.01" ZEC).
37
+ */
38
+ const amountInZec = new BigNumber(amount).shiftedBy(-decimals).toFixed();
39
+
40
+ try {
41
+ const noirWallet = getInstanceOrThrow();
42
+ const zcash = noirWallet.zcash;
43
+
44
+ const txid = await zcash.sendTransaction({
45
+ to: recipientAddress,
46
+ amount: amountInZec,
47
+ fundingSource: 'transparent',
48
+ });
49
+ return { hash: txid };
50
+ } catch (error) {
51
+ if (typeof error === 'string') {
52
+ throw new SignerError(
53
+ SignerErrorCode.UNEXPECTED_BEHAVIOUR,
54
+ error,
55
+ undefined
56
+ );
57
+ }
58
+ throw new SignerError(SignerErrorCode.SEND_TX_ERROR, undefined, error);
59
+ }
60
+ }
61
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { getNoirWallet } from '@noir-wallet/sdk';
2
+
3
+ export const getInstanceOrThrow = () => {
4
+ const noirWallet = getNoirWallet();
5
+ if (!noirWallet) {
6
+ throw new Error('Noir Wallet not installed');
7
+ }
8
+ return noirWallet;
9
+ };