@joeywallet/gemwallet-compat 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Joey Wallet
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,146 @@
1
+ # @joeywallet/gemwallet-compat
2
+
3
+ GemWallet's `@gemwallet/api` surface, implemented over
4
+ [Joey Wallet](https://joeywallet.xyz). Migrate an existing GemWallet dapp by
5
+ changing one import.
6
+
7
+ ```diff
8
+ - import { isInstalled, getAddress, sendPayment } from '@gemwallet/api'
9
+ + import { isInstalled, getAddress, sendPayment } from '@joeywallet/gemwallet-compat'
10
+ ```
11
+
12
+ ```bash
13
+ npm install @joeywallet/gemwallet-compat
14
+ ```
15
+
16
+ Function names, argument shapes and the `{ type, result }` envelope match
17
+ `@gemwallet/api@3.8.0`. You can keep your existing `result.type === 'reject'`
18
+ branches and your existing `try`/`catch` blocks.
19
+
20
+ ---
21
+
22
+ ## What is implemented
23
+
24
+ | Function | Behaviour |
25
+ | -------- | --------- |
26
+ | `isInstalled()` | `{ result: { isInstalled } }`. Answers immediately when Joey is present, otherwise gives it GemWallet's 1-second budget. Never rejects. |
27
+ | `getAddress()` | `{ type, result: { address } }`. Tries a silent connect first, then prompts if the origin is not yet authorised. |
28
+ | `getPublicKey()` | `{ type, result: { address, publicKey } }`. Throws for a watch-only account. |
29
+ | `getNetwork()` | `{ type, result: { chain, network, websocket } }` where `chain` is always `'XRPL'` and `network` is `Mainnet` / `Testnet` / `Devnet`. |
30
+ | `sendPayment(payload)` | Builds a `Payment`, signs and submits. `{ type, result: { hash } }` |
31
+ | `setTrustline(payload)` | Builds a `TrustSet`, signs and submits. `{ type, result: { hash } }` |
32
+ | `signTransaction({ transaction })` | `{ type, result: { signature } }` — `signature` is the signed blob, as in GemWallet. |
33
+ | `submitTransaction({ transaction })` | `{ type, result: { hash } }` |
34
+ | `submitBulkTransactions({ transactions })` | `{ type, result: { transactions: [{ id?, accepted, hash? }] } }` |
35
+ | `on(event, callback)` | `login`, `logout`, `networkChanged`, `walletChanged` |
36
+
37
+ Payload field casing is GemWallet's, not XRPL's: `{ fee, sequence, memos: [{ memo: { memoData } }] }`
38
+ is translated to `{ Fee, Sequence, Memos: [{ Memo: { MemoData } }] }` before
39
+ signing.
40
+
41
+ ### Behavioural differences worth knowing
42
+
43
+ - **`on()` returns an unsubscribe function.** `@gemwallet/api` returns `void`.
44
+ Existing call sites that ignore the return value are unaffected; SPAs that
45
+ re-subscribe on every route change now have a way to avoid leaking listeners.
46
+ - **`on()` accepts both spellings.** `'login'` and the raw wire constant
47
+ `'EVENT_LOGIN'` both work, because `@gemwallet/api`'s implementation compares
48
+ against the latter while its documentation uses the former.
49
+ - **`submitBulkTransactions` always aborts at the first failure.** `onError` is
50
+ accepted and ignored. `'abort'` is GemWallet's own default and the safer of
51
+ the two: `'continue'` would keep signing after a transaction the user or the
52
+ ledger already refused. Entries the aborted batch never reached come back as
53
+ `{ accepted: false }` with no `hash`, correlated to your `ID` by position.
54
+ - **`getNetwork().websocket`** is the public endpoint for the chain Joey is on,
55
+ so it can still be fed to an xrpl.js `Client` the way GemWallet dapps do.
56
+
57
+ ---
58
+
59
+ ## What is deliberately **not** implemented
60
+
61
+ `setRegularKey()`, `setHook()`, `setAccount()` and `signMessage()` throw
62
+ `GemWalletUnsupportedError` (code `4200`) **synchronously**, so you find out at
63
+ the first call in development rather than shipping a dead code path.
64
+
65
+ ### The three account-control transactions
66
+
67
+ - **`SetRegularKey`** assigns an alternate signing key. Combined with
68
+ `AccountSet asfDisableMaster` it hands the holder permanent, unrevokable
69
+ control of the account — and the balance looks untouched while it drains over
70
+ later ledgers.
71
+ - **`SetHook`** installs code that runs on every future transaction for the
72
+ account.
73
+ - **`AccountSet`** can disable the master key, set an NFT minter, or change the
74
+ transfer rate.
75
+
76
+ No approval dialog makes these safe, because the user cannot evaluate the
77
+ consequence from the transaction JSON. Joey supports them from its own UI,
78
+ behind a typed confirmation and step-up authentication, and the extension
79
+ hard-rejects `SetRegularKey`, `SignerListSet` and `AccountDelete` at the
80
+ deserialisation layer for any dapp-originated request — so routing one through
81
+ `signTransaction()` or `submitTransaction()` by hand does not work either.
82
+
83
+ ```ts
84
+ import { GemWalletUnsupportedError, setRegularKey } from '@joeywallet/gemwallet-compat'
85
+
86
+ try {
87
+ await setRegularKey({ regularKey: 'r…' })
88
+ } catch (error) {
89
+ if (error instanceof GemWalletUnsupportedError) {
90
+ // error.method -> 'setRegularKey'
91
+ // error.code -> 4200
92
+ showMessage('Change your account keys from the Joey Wallet extension.')
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### `signMessage`
98
+
99
+ Joey has no raw message-signing method. A bare signature over an arbitrary
100
+ string carries no domain, no nonce and no timestamp, so a signature a user
101
+ produced on one site can be replayed against another. Use `signIn()` from
102
+ [`@joeywallet/wallet-sdk`](../sdk) instead, which signs a CAIP-122 message bound to
103
+ this origin and returns the exact string that was signed for your backend to
104
+ verify:
105
+
106
+ ```ts
107
+ import { requireJoey } from '@joeywallet/wallet-sdk'
108
+
109
+ const { address, publicKey, signature, message } = await requireJoey().signIn({
110
+ statement: 'Sign in to Example',
111
+ })
112
+ ```
113
+
114
+ ### NFT and offer helpers
115
+
116
+ GemWallet's `mintNFT`, `createNFTOffer`, `acceptNFTOffer`, `cancelNFTOffer`,
117
+ `burnNFT`, `getNFT`, `createOffer` and `cancelOffer` are not in this package.
118
+ They carry no security objection — they are ordinary transactions — so build
119
+ them with `submitTransaction({ transaction })`, or use `@joeywallet/wallet-sdk`
120
+ directly.
121
+
122
+ ---
123
+
124
+ ## Once you have migrated
125
+
126
+ This package exists to make the switch free, not to be the destination. When you
127
+ have time, move to [`@joeywallet/wallet-sdk`](../sdk): promise rejections instead of a
128
+ `{ type, result }` envelope, typed events, React hooks, multisign and bulk
129
+ signing.
130
+
131
+ ```ts
132
+ // @joeywallet/gemwallet-compat
133
+ const result = await sendPayment({ amount: '1000000', destination })
134
+ if (result.type === 'reject') return
135
+ console.log(result.result?.hash)
136
+
137
+ // @joeywallet/wallet-sdk
138
+ const { hash } = await joey.signAndSubmitTransaction({
139
+ tx_json: {
140
+ TransactionType: 'Payment',
141
+ Account: address,
142
+ Destination: destination,
143
+ Amount: '1000000',
144
+ },
145
+ })
146
+ ```
@@ -0,0 +1,50 @@
1
+ /**
2
+ * GemWallet request shapes to XRPL transaction JSON.
3
+ *
4
+ * GemWallet's payloads are camelCase and its memo/signer wrappers are lowercase
5
+ * (`{ memo: { memoData } }`), while the ledger — and therefore everything Joey
6
+ * signs — uses XRPL's PascalCase field names. Every mapping here is mechanical;
7
+ * it is separated out because a mistake in it would show up as a transaction
8
+ * that silently loses a destination tag or a memo.
9
+ */
10
+ import type { AnyTransaction, JoeyNetwork, Memo as XrplMemo, Signer as XrplSigner } from '@joeywallet/wallet-sdk';
11
+ import type { BaseTransactionRequest, Memo as GemMemo, Network, SendPaymentRequest, SetTrustlineRequest, Signer as GemSigner } from './types.js';
12
+ export declare function toXrplMemos(memos: GemMemo[] | undefined): XrplMemo[] | undefined;
13
+ export declare function toXrplSigners(signers: GemSigner[] | undefined): XrplSigner[] | undefined;
14
+ /** The fields every GemWallet transaction request shares. */
15
+ export declare function toXrplCommonFields(request: BaseTransactionRequest): Record<string, unknown>;
16
+ /**
17
+ * GemWallet's `sendPayment` payload as an XRPL `Payment`.
18
+ *
19
+ * **`amount` crosses untouched, and that is correct — checked, not assumed.**
20
+ * It is the one line in this package where being wrong costs a factor of a
21
+ * million, so the source is named rather than trusted to memory:
22
+ * `@gemwallet/api@3.8.0` types `SendPaymentRequest.amount` as xrpl.js's
23
+ * `Amount`, and `packages/constants/src/payload/payload.types.ts` documents it
24
+ * verbatim as *"A string representing the number of XRP to deliver, in drops."*
25
+ * Joey's `Payment.Amount` is drops. Same unit, no conversion, and a converting
26
+ * shim here would be the bug rather than the fix.
27
+ *
28
+ * The one place GemWallet does convert is its extension's `parseAmount`, and
29
+ * only for its deprecated v1 URL-parameter path, where `amount` arrives as a
30
+ * *number* of XRP. That path is not this API and never reaches this function:
31
+ * `amount` here is a `string` or an issued-currency object, both of which
32
+ * GemWallet forwards to the ledger exactly as this does.
33
+ *
34
+ * `convert.test.ts` pins both halves — drops for XRP, `value` untouched for an
35
+ * issued currency — so a future "helpful" `xrpToDrops` fails a test instead of
36
+ * a user's payment.
37
+ */
38
+ export declare function toPaymentTransaction(request: SendPaymentRequest, account?: string): AnyTransaction;
39
+ export declare function toTrustSetTransaction(request: SetTrustlineRequest, account?: string): AnyTransaction;
40
+ /**
41
+ * Joey's network to GemWallet's `Network` string.
42
+ *
43
+ * GemWallet also has `Custom`, which Joey never returns: the extension ships a
44
+ * fixed set of three endpoints.
45
+ */
46
+ export declare function toGemNetwork(network: JoeyNetwork): Network;
47
+ export declare function toGemWebsocket(network: JoeyNetwork): string;
48
+ /** GemWallet's human-readable network description, for the event payload. */
49
+ export declare function toGemNetworkDescription(network: JoeyNetwork): string;
50
+ //# sourceMappingURL=convert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.d.ts","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EACV,cAAc,EAEd,WAAW,EACX,IAAI,IAAI,QAAQ,EAChB,MAAM,IAAI,UAAU,EACrB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,KAAK,EACV,sBAAsB,EACtB,IAAI,IAAI,OAAO,EACf,OAAO,EACP,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,IAAI,SAAS,EACpB,MAAM,YAAY,CAAA;AAWnB,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,SAAS,GAAG,QAAQ,EAAE,GAAG,SAAS,CAShF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,GAAG,UAAU,EAAE,GAAG,SAAS,CASxF;AAED,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAc3F;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,MAAM,GACf,cAAc,CAiBhB;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,mBAAmB,EAC5B,OAAO,CAAC,EAAE,MAAM,GACf,cAAc,CAYhB;AAgCD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAE1D;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAE3D;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,GAAG,MAAM,CAEpE"}
@@ -0,0 +1,143 @@
1
+ /** Drops keys whose value is `undefined` so the wire message stays minimal. */
2
+ function defined(source) {
3
+ const out = {};
4
+ for (const [key, value] of Object.entries(source)) {
5
+ if (value !== undefined)
6
+ out[key] = value;
7
+ }
8
+ return out;
9
+ }
10
+ export function toXrplMemos(memos) {
11
+ if (memos === undefined)
12
+ return undefined;
13
+ return memos.map((entry) => ({
14
+ Memo: defined({
15
+ MemoData: entry.memo.memoData,
16
+ MemoType: entry.memo.memoType,
17
+ MemoFormat: entry.memo.memoFormat,
18
+ }),
19
+ }));
20
+ }
21
+ export function toXrplSigners(signers) {
22
+ if (signers === undefined)
23
+ return undefined;
24
+ return signers.map((entry) => ({
25
+ Signer: {
26
+ Account: entry.signer.account,
27
+ TxnSignature: entry.signer.txnSignature,
28
+ SigningPubKey: entry.signer.signingPubKey,
29
+ },
30
+ }));
31
+ }
32
+ /** The fields every GemWallet transaction request shares. */
33
+ export function toXrplCommonFields(request) {
34
+ return defined({
35
+ Fee: request.fee,
36
+ Sequence: request.sequence,
37
+ AccountTxnID: request.accountTxnID,
38
+ LastLedgerSequence: request.lastLedgerSequence,
39
+ Memos: toXrplMemos(request.memos),
40
+ NetworkID: request.networkID,
41
+ Signers: toXrplSigners(request.signers),
42
+ SourceTag: request.sourceTag,
43
+ SigningPubKey: request.signingPubKey,
44
+ TicketSequence: request.ticketSequence,
45
+ TxnSignature: request.txnSignature,
46
+ });
47
+ }
48
+ /**
49
+ * GemWallet's `sendPayment` payload as an XRPL `Payment`.
50
+ *
51
+ * **`amount` crosses untouched, and that is correct — checked, not assumed.**
52
+ * It is the one line in this package where being wrong costs a factor of a
53
+ * million, so the source is named rather than trusted to memory:
54
+ * `@gemwallet/api@3.8.0` types `SendPaymentRequest.amount` as xrpl.js's
55
+ * `Amount`, and `packages/constants/src/payload/payload.types.ts` documents it
56
+ * verbatim as *"A string representing the number of XRP to deliver, in drops."*
57
+ * Joey's `Payment.Amount` is drops. Same unit, no conversion, and a converting
58
+ * shim here would be the bug rather than the fix.
59
+ *
60
+ * The one place GemWallet does convert is its extension's `parseAmount`, and
61
+ * only for its deprecated v1 URL-parameter path, where `amount` arrives as a
62
+ * *number* of XRP. That path is not this API and never reaches this function:
63
+ * `amount` here is a `string` or an issued-currency object, both of which
64
+ * GemWallet forwards to the ledger exactly as this does.
65
+ *
66
+ * `convert.test.ts` pins both halves — drops for XRP, `value` untouched for an
67
+ * issued currency — so a future "helpful" `xrpToDrops` fails a test instead of
68
+ * a user's payment.
69
+ */
70
+ export function toPaymentTransaction(request, account) {
71
+ return {
72
+ TransactionType: 'Payment',
73
+ ...(account === undefined ? {} : { Account: account }),
74
+ ...toXrplCommonFields(request),
75
+ ...defined({
76
+ // Drops. See the note above before changing this.
77
+ Amount: request.amount,
78
+ Destination: request.destination,
79
+ DestinationTag: request.destinationTag,
80
+ InvoiceID: request.invoiceID,
81
+ Paths: request.paths,
82
+ SendMax: request.sendMax,
83
+ DeliverMin: request.deliverMin,
84
+ Flags: request.flags,
85
+ }),
86
+ };
87
+ }
88
+ export function toTrustSetTransaction(request, account) {
89
+ return {
90
+ TransactionType: 'TrustSet',
91
+ ...(account === undefined ? {} : { Account: account }),
92
+ ...toXrplCommonFields(request),
93
+ ...defined({
94
+ LimitAmount: request.limitAmount,
95
+ QualityIn: request.qualityIn,
96
+ QualityOut: request.qualityOut,
97
+ Flags: request.flags,
98
+ }),
99
+ };
100
+ }
101
+ /* ------------------------------------------------------------------ networks */
102
+ /**
103
+ * The public endpoints for each chain.
104
+ *
105
+ * Duplicated from the extension's `shared/types.ts` `NETWORKS` rather than
106
+ * imported: this package is published to npm and cannot depend on the
107
+ * extension's source. GemWallet's `getNetwork()` contract promises a
108
+ * `websocket`, and dapps feed it straight into an xrpl.js `Client`, so
109
+ * answering with an empty string would break every migrating caller. They must
110
+ * be kept in step with the extension if an endpoint ever moves.
111
+ */
112
+ const WEBSOCKET_BY_CHAIN = {
113
+ 'xrpl:0': 'wss://s1.ripple.com/',
114
+ 'xrpl:1': 'wss://testnet.xrpl-labs.com/',
115
+ 'xrpl:2': 'wss://s.devnet.rippletest.net:51233/',
116
+ };
117
+ const GEM_NAME_BY_CHAIN = {
118
+ 'xrpl:0': 'Mainnet',
119
+ 'xrpl:1': 'Testnet',
120
+ 'xrpl:2': 'Devnet',
121
+ };
122
+ const DESCRIPTION_BY_CHAIN = {
123
+ 'xrpl:0': 'Main XRPL network',
124
+ 'xrpl:1': 'XRPL Testnet',
125
+ 'xrpl:2': 'XRPL Devnet',
126
+ };
127
+ /**
128
+ * Joey's network to GemWallet's `Network` string.
129
+ *
130
+ * GemWallet also has `Custom`, which Joey never returns: the extension ships a
131
+ * fixed set of three endpoints.
132
+ */
133
+ export function toGemNetwork(network) {
134
+ return GEM_NAME_BY_CHAIN[network.chain];
135
+ }
136
+ export function toGemWebsocket(network) {
137
+ return WEBSOCKET_BY_CHAIN[network.chain];
138
+ }
139
+ /** GemWallet's human-readable network description, for the event payload. */
140
+ export function toGemNetworkDescription(network) {
141
+ return DESCRIPTION_BY_CHAIN[network.chain];
142
+ }
143
+ //# sourceMappingURL=convert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"convert.js","sourceRoot":"","sources":["../src/convert.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { BaseResponse } from './types.js';
2
+ export declare function response<T>(result: T): BaseResponse<T> & {
3
+ type: 'response';
4
+ result: T;
5
+ };
6
+ export declare function rejected<T>(): BaseResponse<T> & {
7
+ type: 'reject';
8
+ };
9
+ export declare function envelope<T>(run: () => Promise<T>): Promise<BaseResponse<T>>;
10
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAExF;AAED,wBAAgB,QAAQ,CAAC,CAAC,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAElE;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAOjF"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * GemWallet's `{ type, result }` envelope, reconstructed on top of Joey's
3
+ * promise-rejection API.
4
+ *
5
+ * The two models disagree about exactly one thing, and this file is where that
6
+ * disagreement is resolved: GemWallet reports a user declining as a *resolved*
7
+ * `{ type: 'reject' }`, and reports everything else by throwing. Joey rejects
8
+ * with a `JoeyRpcError` in both cases. So a 4001 becomes `{ type: 'reject' }`
9
+ * and every other code is rethrown, which is what a GemWallet dapp's existing
10
+ * `if (result.type === 'reject')` branch and its `try`/`catch` already expect.
11
+ */
12
+ import { JoeyRpcError, isUserRejection } from '@joeywallet/wallet-sdk';
13
+ export function response(result) {
14
+ return { type: 'response', result };
15
+ }
16
+ export function rejected() {
17
+ return { type: 'reject', result: undefined };
18
+ }
19
+ export async function envelope(run) {
20
+ try {
21
+ return response(await run());
22
+ }
23
+ catch (cause) {
24
+ if (isUserRejection(cause))
25
+ return rejected();
26
+ throw JoeyRpcError.from(cause);
27
+ }
28
+ }
29
+ //# sourceMappingURL=envelope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.js","sourceRoot":"","sources":["../src/envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAA;AAItE,MAAM,UAAU,QAAQ,CAAI,MAAS;IACnC,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAA;AACrC,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,CAAA;AAC9C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,GAAqB;IACrD,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,eAAe,CAAC,KAAK,CAAC;YAAE,OAAO,QAAQ,EAAK,CAAA;QAChD,MAAM,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;AACH,CAAC"}
@@ -0,0 +1,51 @@
1
+ import type { GemEventPayloadMap, GemEventType, GetAddressResponse, GetNetworkResponse, GetPublicKeyResponse, IsInstalledResponse, SendPaymentRequest, SendPaymentResponse, SetTrustlineRequest, SetTrustlineResponse, SignMessageResponse, SignTransactionRequest, SignTransactionResponse, SubmitBulkTransactionsRequest, SubmitBulkTransactionsResponse, SubmitTransactionRequest, SubmitTransactionResponse } from './types.js';
2
+ /**
3
+ * Never rejects, and answers immediately when the provider is already present.
4
+ *
5
+ * Matches GemWallet's contract, including its 1-second budget for a provider
6
+ * that has not been injected yet.
7
+ */
8
+ export declare function isInstalled(): Promise<IsInstalledResponse>;
9
+ export declare function getAddress(): Promise<GetAddressResponse>;
10
+ export declare function getPublicKey(): Promise<GetPublicKeyResponse>;
11
+ export declare function getNetwork(): Promise<GetNetworkResponse>;
12
+ /**
13
+ * Not implemented. Throws {@link GemWalletUnsupportedError} synchronously.
14
+ *
15
+ * Joey has no raw message-signing method: a bare signature over a string
16
+ * carries no domain, nonce or timestamp and is replayable against another site.
17
+ * Use `signIn()` from `@joeywallet/wallet-sdk`, which signs a CAIP-122 message bound
18
+ * to this origin.
19
+ */
20
+ export declare function signMessage(_message: string, _isHex?: boolean): Promise<SignMessageResponse>;
21
+ export declare function sendPayment(paymentPayload: SendPaymentRequest): Promise<SendPaymentResponse>;
22
+ export declare function setTrustline(payload: SetTrustlineRequest): Promise<SetTrustlineResponse>;
23
+ export declare function signTransaction(payload: SignTransactionRequest): Promise<SignTransactionResponse>;
24
+ export declare function submitTransaction(payload: SubmitTransactionRequest): Promise<SubmitTransactionResponse>;
25
+ export declare function submitBulkTransactions(payload: SubmitBulkTransactionsRequest): Promise<SubmitBulkTransactionsResponse>;
26
+ /**
27
+ * Not implemented. Throws {@link GemWalletUnsupportedError} synchronously.
28
+ *
29
+ * @see ./unsupported.ts for why.
30
+ */
31
+ export declare function setRegularKey(_payload?: unknown): Promise<never>;
32
+ /** Not implemented. Throws {@link GemWalletUnsupportedError} synchronously. */
33
+ export declare function setHook(_payload?: unknown): Promise<never>;
34
+ /** Not implemented. Throws {@link GemWalletUnsupportedError} synchronously. */
35
+ export declare function setAccount(_payload?: unknown): Promise<never>;
36
+ type NormalisedEvent<E extends GemEventType> = E extends 'login' | 'EVENT_LOGIN' ? 'login' : E extends 'logout' | 'EVENT_LOGOUT' ? 'logout' : E extends 'networkChanged' | 'EVENT_NETWORK_CHANGED' ? 'networkChanged' : E extends 'walletChanged' | 'EVENT_WALLET_CHANGED' ? 'walletChanged' : never;
37
+ /**
38
+ * Subscribe to a wallet event.
39
+ *
40
+ * `@gemwallet/api`'s `on()` returns `void`; this returns an unsubscribe
41
+ * function. That is a superset — existing call sites that ignore the return
42
+ * value are unaffected — and it is what a single-page app needs to avoid
43
+ * leaking a listener on every route change.
44
+ */
45
+ export declare function on<E extends GemEventType>(eventType: E, callback: (payload: GemEventPayloadMap[NormalisedEvent<E>]) => void): () => void;
46
+ export { GemWalletUnsupportedError, UNSUPPORTED_METHODS, type UnsupportedMethod, } from './unsupported.js';
47
+ export { envelope, rejected, response } from './envelope.js';
48
+ export { toGemNetwork, toGemWebsocket, toPaymentTransaction, toTrustSetTransaction, toXrplMemos, toXrplSigners, } from './convert.js';
49
+ export { DEFAULT_SUBMIT_TX_BULK_ON_ERROR } from './types.js';
50
+ export type * from './types.js';
51
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAKV,kBAAkB,EAClB,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,6BAA6B,EAC7B,8BAA8B,EAC9B,wBAAwB,EACxB,yBAAyB,EAE1B,MAAM,YAAY,CAAA;AA4CnB;;;;;GAKG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAQhE;AAID,wBAAsB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAK9D;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,oBAAoB,CAAC,CAWlE;AAED,wBAAsB,UAAU,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAW9D;AAID;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAE5F;AAED,wBAAsB,WAAW,CAC/B,cAAc,EAAE,kBAAkB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAQ9B;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAQ/B;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,uBAAuB,CAAC,CAQlC;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,yBAAyB,CAAC,CAMpC;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,6BAA6B,GACrC,OAAO,CAAC,8BAA8B,CAAC,CAwCzC;AAID;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAEhE;AAED,+EAA+E;AAC/E,wBAAgB,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAE1D;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAE7D;AAID,KAAK,eAAe,CAAC,CAAC,SAAS,YAAY,IAAI,CAAC,SAAS,OAAO,GAAG,aAAa,GAC5E,OAAO,GACP,CAAC,SAAS,QAAQ,GAAG,cAAc,GACjC,QAAQ,GACR,CAAC,SAAS,gBAAgB,GAAG,uBAAuB,GAClD,gBAAgB,GAChB,CAAC,SAAS,eAAe,GAAG,sBAAsB,GAChD,eAAe,GACf,KAAK,CAAA;AAwDf;;;;;;;GAOG;AACH,wBAAgB,EAAE,CAAC,CAAC,SAAS,YAAY,EACvC,SAAS,EAAE,CAAC,EACZ,QAAQ,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,GAClE,MAAM,IAAI,CAyBZ;AAID,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC5D,OAAO,EACL,YAAY,EACZ,cAAc,EACd,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,+BAA+B,EAAE,MAAM,YAAY,CAAA;AAC5D,mBAAmB,YAAY,CAAA"}