-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/integrate gem wallet #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: next
Are you sure you want to change the base?
Changes from all commits
42c3ad9
e08991b
56faf11
190e308
2bae0f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,6 +36,8 @@ export function scheduleNextStep({ | |
| (step: PendingSwapStep) => step.status === 'failed' | ||
| ); | ||
|
|
||
| console.log('what the heck is happening here'); | ||
|
|
||
|
Comment on lines
+39
to
+40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1. Stray debug log scheduleNextStep now prints a hardcoded debug message on every execution, creating noisy production logs and potentially leaking internal behavior during swaps. Agent Prompt
|
||
| if (!!currentStep && !isFailed) { | ||
| if (isTxAlreadyCreated(swap, currentStep)) { | ||
| if (currentStep.fromBlockchain === TransactionType.XRPL) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| export * as builders from './builders.js'; | ||
| export type { XRPLActions } from './types.js'; | ||
|
|
||
| export * as utils from './utils.js'; | ||
| export { CAIP_XRPL_CHAIN_ID, CAIP_NAMESPACE } from './constants.js'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| import type { CaipAccount } from '../common/mod.js'; | ||
|
|
||
| import { AccountId } from 'caip'; | ||
|
|
||
| import { CAIP_NAMESPACE, CAIP_XRPL_CHAIN_ID } from './constants.js'; | ||
|
|
||
| export function formatAddressToCAIP(address: string): string { | ||
| return AccountId.format({ | ||
| address, | ||
| chainId: { | ||
| namespace: CAIP_NAMESPACE, | ||
| reference: CAIP_XRPL_CHAIN_ID, | ||
| }, | ||
| }) as CaipAccount; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| { | ||
| "name": "@rango-dev/provider-gemwallet", | ||
| "version": "0.1.0", | ||
| "license": "MIT", | ||
| "type": "module", | ||
| "source": "./src/mod.ts", | ||
| "main": "./dist/mod.js", | ||
| "exports": { | ||
| ".": "./dist/mod.js" | ||
| }, | ||
| "typings": "dist/mod.d.ts", | ||
| "files": [ | ||
| "dist", | ||
| "src" | ||
| ], | ||
| "scripts": { | ||
| "build": "node ../../scripts/build/command.mjs --path wallets/provider-gemwallet --inputs src/mod.ts", | ||
| "ts-check": "tsc --declaration --emitDeclarationOnly -p ./tsconfig.json", | ||
| "clean": "rimraf dist", | ||
| "format": "prettier --write '{.,src}/**/*.{ts,tsx}'", | ||
| "lint": "eslint \"**/*.{ts,tsx}\"" | ||
| }, | ||
| "dependencies": { | ||
| "@rango-dev/wallets-shared": "0.58.1-next.2", | ||
| "@gemwallet/api": "^3.8.0", | ||
| "xrpl": "^4.2.0", | ||
| "rango-types": "^0.1.95" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,18 @@ | ||||||
| # GemWallet Provider | ||||||
| GemWallet integration for hub. | ||||||
| [Homepage](https://gemwallet.app/) | [Docs](https://gemwallet.app/docs/user-guide/introduction) | ||||||
|
|
||||||
| More about implementation status can be found [here](../readme.md). | ||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use descriptive link text instead of “here”. Line 5 uses non-descriptive link text, which hurts readability/accessibility in docs and rendered link lists. Suggested doc tweak-More about implementation status can be found [here](../readme.md).
+More about implementation status can be found in the [wallet providers implementation status](../readme.md).📝 Committable suggestion
Suggested change
🧰 Tools🪛 markdownlint-cli2 (0.22.0)[warning] 5-5: Link text should be descriptive (MD059, descriptive-link-text) 🤖 Prompt for AI Agents |
||||||
|
|
||||||
| ## Implementation notes/limitation | ||||||
|
|
||||||
| ### Feature | ||||||
|
|
||||||
| #### ⚠️ Auto Connect | ||||||
|
|
||||||
| It doesn't have the feature to silently connect to wallet, it shows a popup and a loading for a few seconds. | ||||||
|
|
||||||
|
|
||||||
| --- | ||||||
|
|
||||||
| More wallet information can be found in [readme.md](../readme.md). | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| import type { ProviderMetadata } from '@rango-dev/wallets-core'; | ||
| import type { BlockchainMeta } from 'rango-types'; | ||
|
|
||
| import { xrplBlockchain } from 'rango-types'; | ||
|
|
||
| import getSigners from './signer.js'; | ||
|
|
||
| export const XRPL_PUBLIC_SERVER = 'wss://xrplcluster.com/'; | ||
| export const WALLET_ID = 'gemwallet'; | ||
|
|
||
| export const info: ProviderMetadata = { | ||
| name: 'GemWallet', | ||
| icon: 'https://raw.githubusercontent.com/rango-exchange/assets/main/wallets/gemwallet/icon.svg', | ||
| extensions: { | ||
| chrome: | ||
| 'https://chromewebstore.google.com/detail/gemwallet/egebedonbdapoieedfcfkofloclfghab', | ||
| homepage: 'https://gemwallet.app/', | ||
| }, | ||
| properties: [ | ||
| { | ||
| name: 'namespaces', | ||
| value: { | ||
| selection: 'multiple', | ||
| data: [ | ||
| { | ||
| label: 'XRPL', | ||
| value: 'XRPL', | ||
| id: 'XRPL', | ||
| getSupportedChains: (allBlockchains: BlockchainMeta[]) => | ||
| xrplBlockchain(allBlockchains), | ||
|
Comment on lines
+29
to
+30
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typos in variable names and file paths causing runtime errors. In This issue appears in multiple locations:
getSupportedChains: (allBlockchains: BlockchainMeta[]) =>
xrplBlockchain(allBlockchains),Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||
| }, | ||
| ], | ||
| }, | ||
| }, | ||
| { | ||
| name: 'signers', | ||
| value: { getSigners: async () => getSigners() }, | ||
| }, | ||
| ], | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| import { defineVersions } from '@rango-dev/wallets-core/utils'; | ||
|
|
||
| import { buildProvider } from './provider.js'; | ||
|
|
||
| const versions = () => | ||
| defineVersions().version('1.0.0', buildProvider()).build(); | ||
|
|
||
| export { versions }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| import type { | ||
| Memo, | ||
| SendPaymentRequest, | ||
| SetTrustlineRequest, | ||
| } from '@gemwallet/api'; | ||
| import type { | ||
| XrplPaymentTransactionData, | ||
| XrplTransactionDataIssuedCurrencyAmount, | ||
| XrplTransactionDataMPTAmount, | ||
| XrplTrustSetTransactionData, | ||
| } from 'rango-types/mainApi'; | ||
|
|
||
| function isIssuedCurrencyAmount( | ||
| amount: XrplPaymentTransactionData['Amount'] | ||
| ): amount is XrplTransactionDataIssuedCurrencyAmount { | ||
| return ( | ||
| typeof amount === 'object' && | ||
| // @ts-expect-error it never throw an runtime error, since we are checking it should be an object first | ||
| typeof amount.currency === 'string' && | ||
| // @ts-expect-error it never throw an runtime error, since we are checking it should be an object first | ||
| typeof amount.issuer === 'string' && | ||
| typeof amount.value === 'string' | ||
|
Comment on lines
+16
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make the XRPL amount guards null-safe.
🛠️ Suggested change function isIssuedCurrencyAmount(
amount: XrplPaymentTransactionData['Amount']
): amount is XrplTransactionDataIssuedCurrencyAmount {
- return (
- typeof amount === 'object' &&
- // `@ts-expect-error` it never throw an runtime error, since we are checking it should be an object first
- typeof amount.currency === 'string' &&
- // `@ts-expect-error` it never throw an runtime error, since we are checking it should be an object first
- typeof amount.issuer === 'string' &&
- typeof amount.value === 'string'
- );
+ return !!amount &&
+ typeof amount === 'object' &&
+ 'currency' in amount &&
+ typeof amount.currency === 'string' &&
+ 'issuer' in amount &&
+ typeof amount.issuer === 'string' &&
+ 'value' in amount &&
+ typeof amount.value === 'string';
}
function isMPTokenAmount(
amount: XrplPaymentTransactionData['Amount']
): amount is XrplTransactionDataMPTAmount {
- return (
- typeof amount === 'object' &&
- // `@ts-expect-error` it never throw an runtime error, since we are checking it should be an object first
- typeof amount.mpt_issuance_id === 'string' &&
- typeof amount.value === 'string'
- );
+ return !!amount &&
+ typeof amount === 'object' &&
+ 'mpt_issuance_id' in amount &&
+ typeof amount.mpt_issuance_id === 'string' &&
+ 'value' in amount &&
+ typeof amount.value === 'string';
}Also applies to: 30-33 🤖 Prompt for AI Agents |
||
| ); | ||
| } | ||
|
|
||
| function isMPTokenAmount( | ||
| amount: XrplPaymentTransactionData['Amount'] | ||
| ): amount is XrplTransactionDataMPTAmount { | ||
| return ( | ||
| typeof amount === 'object' && | ||
| // @ts-expect-error it never throw an runtime error, since we are checking it should be an object first | ||
| typeof amount.mpt_issuance_id === 'string' && | ||
| typeof amount.value === 'string' | ||
| ); | ||
| } | ||
|
|
||
| function fromPaymentTransactionMemoToGemWalletMemo( | ||
| memos: XrplPaymentTransactionData['Memos'] | ||
| ): Memo[] { | ||
| if (!memos) { | ||
| return []; | ||
| } | ||
|
|
||
| return memos.map((memo) => { | ||
| return { | ||
| memo: { | ||
| memoType: memo.Memo.MemoType, | ||
| memoData: memo.Memo.MemoData, | ||
| memoFormat: memo.Memo.MemoFormat, | ||
| }, | ||
| }; | ||
| }); | ||
| } | ||
|
|
||
| export function fromTrustSetTransactionDataToGemWalletRequest( | ||
| data: XrplTrustSetTransactionData | ||
| ): SetTrustlineRequest { | ||
| return { | ||
| limitAmount: data.LimitAmount, | ||
| memos: fromPaymentTransactionMemoToGemWalletMemo(data.Memos), | ||
| flags: data.Flags, | ||
| }; | ||
| } | ||
|
|
||
| export function fromPaymentTransactionDataToGemWalletRequest( | ||
| data: XrplPaymentTransactionData | ||
| ): SendPaymentRequest { | ||
| let amount: SendPaymentRequest['amount']; | ||
| if (isMPTokenAmount(data.Amount)) { | ||
| throw new Error("Current implemented signer doesn't have support for MPT"); | ||
| } else if (isIssuedCurrencyAmount(data.Amount)) { | ||
| amount = data.Amount; | ||
| } else if (typeof data.Amount === 'string') { | ||
| amount = data.Amount; | ||
| } else { | ||
| throw new Error( | ||
| "There is an unexpected type for Amount. current signer doesn't have support for that." | ||
| ); | ||
| } | ||
|
|
||
| return { | ||
| amount, | ||
| destination: data.Destination, | ||
| destinationTag: data.DestinationTag, | ||
| memos: fromPaymentTransactionMemoToGemWalletMemo(data.Memos), | ||
| flags: data.Flags, | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,35 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { XRPLActions } from '@rango-dev/wallets-core/namespaces/xrpl'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { on } from '@gemwallet/api'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ChangeAccountSubscriberBuilder } from '@rango-dev/wallets-core/namespaces/common'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { utils } from '@rango-dev/wallets-core/namespaces/xrpl'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type WalletChangedEventPayload = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wallet: { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| publicAddress: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function changeAccountSubscriberBuilder() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // `true` instead of ProviderAPI is just a workaround. we don't need to have instance here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return new ChangeAccountSubscriberBuilder< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| WalletChangedEventPayload, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| XRPLActions | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .getInstance(() => true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .format(async (_, payload) => [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| utils.formatAddressToCAIP(payload.wallet.publicAddress), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .addEventListener((_, callback) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| on('walletChanged', callback); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .removeEventListener((_instance, _callback) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /* | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * TODO: gem wallet doesn't have support for unsubscribing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * Making a variable and keep the callback refrence then here make it `undefined` is a quick fix | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| * but it makes new bugs, where if two subscribers added at once, we will loose the track of the first one and it will be staled. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+27
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resource leaks due to improper cleanup. In This issue appears in multiple locations:
.removeEventListener((_instance, _callback) => {
// TODO: gem wallet doesn't have support for unsubscribing.
// This feature will cause memory leaks until the underlying API supports listener removal.
console.warn(
'GemWallet provider does not support unsubscribing from "walletChanged" events. This will cause a memory leak.'
);
})Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.
Comment on lines
+24
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: No, Citations:
Remove no-op
Implement a local Set-based fan-out registry to manage subscribers independently of the provider's single registration: Suggested implementation+const walletChangedSubscribers = new Set<(payload: WalletChangedEventPayload) => void>();
+let bridgeRegistered = false;
+
+const walletChangedBridge = (payload: WalletChangedEventPayload) => {
+ for (const cb of walletChangedSubscribers) cb(payload);
+};
+
export function changeAccountSubscriberBuilder() {
return new ChangeAccountSubscriberBuilder<
WalletChangedEventPayload,
true,
XRPLActions
>()
.getInstance(() => true)
.format(async (_, payload) => [
utils.formatAddressToCAIP(payload.wallet.publicAddress),
])
.addEventListener((_, callback) => {
- on('walletChanged', callback);
+ if (!bridgeRegistered) {
+ on('walletChanged', walletChangedBridge);
+ bridgeRegistered = true;
+ }
+ walletChangedSubscribers.add(callback);
})
- .removeEventListener((_instance, _callback) => {
- /*
- * TODO: gem wallet doesn't have support for unsubscribing.
- * Making a variable and keep the callback refrence then here make it `undefined` is a quick fix
- * but it makes new bugs, where if two subscribers added at once, we will loose the track of the first one and it will be staled.
- */
+ .removeEventListener((_instance, callback) => {
+ walletChangedSubscribers.delete(callback);
})
.build();
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Comment on lines
+24
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 3. Account listener not removable GemWallet's account-change subscriber registers a walletChanged listener but provides a no-op removeEventListener, so cleanup cannot detach callbacks and repeated subscriptions can accumulate and duplicate state updates. Agent Prompt
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export { namespace } from './namespace.js'; | ||
| export { Signer } from './singer.js'; |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,75 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import type { XRPLActions } from '@rango-dev/wallets-core/namespaces/xrpl'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { getAddress } from '@gemwallet/api'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { ActionBuilder, NamespaceBuilder } from '@rango-dev/wallets-core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { builders, utils } from '@rango-dev/wallets-core/namespaces/xrpl'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { Client } from 'xrpl'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { WALLET_ID, XRPL_PUBLIC_SERVER } from '../../constants.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { checkInstallationOnLoad } from '../../utils.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { changeAccountSubscriberBuilder } from './hooks.js'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [changeAccountSubscriber, changeAccountCleanup] = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| changeAccountSubscriberBuilder(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const connect = builders | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .connect() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(async function () { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await getAddress(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!response.result?.address) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error(`Couldn't access to your wallet address.`); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return [utils.formatAddressToCAIP(response.result.address)]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .before(changeAccountSubscriber) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .or(changeAccountCleanup) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const canEagerConnect = new ActionBuilder<XRPLActions, 'canEagerConnect'>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'canEagerConnect' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(async () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isInstalled = await checkInstallationOnLoad(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!isInstalled) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw new Error( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'Trying to eagerly connect to your EVM wallet, but seems its instance is not available.' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+36
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix wallet type in error message. Line 37 says “EVM wallet” in an XRPL namespace path; this is misleading for users and debugging. Suggested text fix- 'Trying to eagerly connect to your EVM wallet, but seems its instance is not available.'
+ 'Trying to eagerly connect to your XRPL wallet, but its instance is not available.'📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await getAddress(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const address = response.result?.address; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return !!address; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return false; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const accountLines = new ActionBuilder<XRPLActions, 'accountLines'>( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'accountLines' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(async (_, account, options) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The This issue appears in multiple locations:
Suggested change
WarningThis is an experimental feature that generates committable changes. Review the diff before applying. Results may be incorrect. Prompt for LLMTalk to Kody by mentioning @kody Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = new Client(XRPL_PUBLIC_SERVER); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await client.connect(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await client.request({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command: 'account_lines', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ledger_index: 'current', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| account: account, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| peer: options?.peer, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await client.disconnect(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return response.result.lines; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Inspect other XRPL namespace implementations for client lifecycle pattern consistency.
rg -n -C3 'new Client\(|client\.connect\(|client\.disconnect\(' --type=tsRepository: RyukTheCoder/rango-client Length of output: 3090 🏁 Script executed: # Check the full namespace file to see all action handlers and client usage patterns
cat -n wallets/provider-gemwallet/src/namespaces/xrpl/namespace.tsRepository: RyukTheCoder/rango-client Length of output: 2687 🏁 Script executed: # Search for all client lifecycle patterns in the XRPL namespace directory
rg -n 'new Client|\.connect\(|\.disconnect\(' wallets/provider-gemwallet/src/namespaces/xrpl/ --type=ts -C2Repository: RyukTheCoder/rango-client Length of output: 1440 Wrap client request in try-finally to ensure disconnect on errors. If Proposed fix .action(async (_, account, options) => {
const client = new Client(XRPL_PUBLIC_SERVER);
- await client.connect();
-
- const response = await client.request({
- command: 'account_lines',
- ledger_index: 'current',
- account: account,
- peer: options?.peer,
- });
-
- await client.disconnect();
- return response.result.lines;
+ await client.connect();
+ try {
+ const response = await client.request({
+ command: 'account_lines',
+ ledger_index: 'current',
+ account: account,
+ peer: options?.peer,
+ });
+ return response.result.lines;
+ } finally {
+ await client.disconnect();
+ }
})📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Comment on lines
+55
to
+67
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 4. Xrpl client leak on error accountLines connects an xrpl Client and disconnects only on the success path; if connect() or request() throws, the websocket may remain open and leak resources. Agent Prompt
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export const namespace = new NamespaceBuilder<XRPLActions>('XRPL', WALLET_ID) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(connect) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(canEagerConnect) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .action(accountLines) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .build(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this debug log from the scheduler hot path.
Line 39 logs on every
scheduleNextStepcall, which can flood logs and add noise in production. The message is also non-actionable.Proposed fix
- console.log('what the heck is happening here');📝 Committable suggestion
🤖 Prompt for AI Agents