Skip to content

Commit cfab98e

Browse files
committed
fix: allow passing kit functions by reference
What ---- Define methods using `methodName = async () => {…}` syntax, rather than `async methodName() {…}` Why --- This allows for better APIs when using StellarWalletsKit. For example, given a `stellar-wallets-kit.ts` file in my own project with: ```ts const kit: StellarWalletsKit = new StellarWalletsKit({…}); export const signTransaction = kit.signTransaction; ``` And I then use this in my app: ```ts const tx = await incrementor.increment(); const { result } = await tx.signAndSend({ signTransaction }) ``` Today, the `signAndSend` will throw a runtime error: ``` TypeError: Cannot read properties of undefined (reading 'selectedModule') ``` This is because JavaScript's default behavior is coo coo bananas, no one understands it, and `this` ends up getting bound to `undefined` if you use the `async methodName() {…}` syntax and then pass `methodName` as a reference the way I did. Today, in order to make my code work, I would need to export the whole `kit` and then change my `signAndSend` line to: ```ts const { result } = await tx.signAndSend({ signTransaction: async (xdr) => { return await kit.signTransaction(xdr); }, }); ``` I don't like this because A) it's ugly and B) I don't think it's good practice to export the whole `kit`. Within my app, I want to have the ability to wrap interfaces like `signTransaction`, so that I can always make sure app-specific logic gets taken care of. Exporting all of `kit` adds more room for error. The Fix ------- Using the arrow syntax with `methodName = async (…) => {…}` makes JS use similar `this`-binding logic to every other language, and makes my pass-by-reference use-case possible.
1 parent 97dbed6 commit cfab98e

1 file changed

Lines changed: 29 additions & 29 deletions

File tree

src/stellar-wallets-kit.ts

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export class StellarWalletsKit implements KitActions {
6565
* This method will return an array with all wallets supported by this kit but will let you know those the user have already installed/has access to
6666
* There are wallets that are by default available since they either don't need to be installed or have a fallback
6767
*/
68-
public async getSupportedWallets(): Promise<ISupportedWallet[]> {
68+
public getSupportedWallets = async (): Promise<ISupportedWallet[]> => {
6969
return Promise.all(
7070
this.modules.map(async (mod: ModuleInterface): Promise<ISupportedWallet> => {
7171
const timer: Promise<false> = new Promise(r => setTimeout(() => r(false), 500));
@@ -79,9 +79,9 @@ export class StellarWalletsKit implements KitActions {
7979
};
8080
})
8181
);
82-
}
82+
};
8383

84-
public setWallet(id: string): void {
84+
public setWallet = (id: string): void => {
8585
const target: ModuleInterface | undefined = this.modules.find(
8686
(mod: ModuleInterface): boolean => mod.productId === id
8787
);
@@ -91,15 +91,15 @@ export class StellarWalletsKit implements KitActions {
9191
}
9292

9393
setSelectedModuleId(target.productId);
94-
}
94+
};
9595

96-
public async getAddress(params?: { path?: string }): Promise<{ address: string }> {
96+
public getAddress = async (params?: { path?: string }): Promise<{ address: string }> => {
9797
const { address } = await this.selectedModule.getAddress(params);
9898
setAddress(address);
9999
return { address };
100-
}
100+
};
101101

102-
public async signTransaction(
102+
public signTransaction = (
103103
xdr: string,
104104
opts?: {
105105
networkPassphrase?: string;
@@ -108,61 +108,61 @@ export class StellarWalletsKit implements KitActions {
108108
submit?: boolean;
109109
submitUrl?: string;
110110
}
111-
): Promise<{ signedTxXdr: string; signerAddress?: string }> {
111+
): Promise<{ signedTxXdr: string; signerAddress?: string }> => {
112112
return this.selectedModule.signTransaction(xdr, {
113113
...opts,
114114
networkPassphrase: opts?.networkPassphrase || store.getValue().selectedNetwork,
115115
});
116-
}
116+
};
117117

118-
public async signAuthEntry(
118+
public signAuthEntry = (
119119
authEntry: string,
120120
opts?: {
121121
networkPassphrase?: string;
122122
address?: string;
123123
path?: string;
124124
}
125-
): Promise<{ signedAuthEntry: string; signerAddress?: string }> {
125+
): Promise<{ signedAuthEntry: string; signerAddress?: string }> => {
126126
return this.selectedModule.signAuthEntry(authEntry, {
127127
...opts,
128128
networkPassphrase: opts?.networkPassphrase || store.getValue().selectedNetwork,
129129
});
130-
}
130+
};
131131

132-
public async signMessage(
132+
public signMessage = (
133133
message: string,
134134
opts?: {
135135
networkPassphrase?: string;
136136
address?: string;
137137
path?: string;
138138
}
139-
): Promise<{ signedMessage: string; signerAddress?: string }> {
139+
): Promise<{ signedMessage: string; signerAddress?: string }> => {
140140
return this.selectedModule.signMessage(message, {
141141
...opts,
142142
networkPassphrase: opts?.networkPassphrase || store.getValue().selectedNetwork,
143143
});
144-
}
144+
};
145145

146-
async getNetwork(): Promise<{ network: string; networkPassphrase: string }> {
146+
public getNetwork = (): Promise<{ network: string; networkPassphrase: string }> => {
147147
return this.selectedModule.getNetwork();
148-
}
148+
};
149149

150-
async disconnect(): Promise<void> {
150+
public disconnect = async (): Promise<void> => {
151151
removeAddress();
152-
}
152+
};
153153

154154
// ---- Button methods
155-
public isButtonCreated(): boolean {
155+
public isButtonCreated = (): boolean => {
156156
return !!this.buttonElement;
157-
}
157+
};
158158

159-
public async createButton(params: {
159+
public createButton = async (params: {
160160
container: HTMLElement;
161161
onConnect: (response: { address: string }) => void;
162162
onDisconnect: () => void;
163163
horizonUrl?: string;
164164
buttonText?: string;
165-
}): Promise<void> {
165+
}): Promise<void> => {
166166
if (this.buttonElement) {
167167
throw new Error(`Stellar Wallets Kit button is already created`);
168168
}
@@ -203,14 +203,14 @@ export class StellarWalletsKit implements KitActions {
203203
},
204204
false
205205
);
206-
}
206+
};
207207

208208
/**
209209
* Removes the button elements from the HTML and from the kit's instance.
210210
*
211211
* @param params.skipDisconnect - Set this to `true` if you want to prevent that we disconnect (for example, disconnecting WalletConnect or removing the address)
212212
*/
213-
public async removeButton(params?: { skipDisconnect?: boolean }): Promise<void> {
213+
public removeButton = async (params?: { skipDisconnect?: boolean }): Promise<void> => {
214214
if (!this.buttonElement) {
215215
throw new Error(`Stellar Wallets Kit button hasn't been created yet`);
216216
}
@@ -221,16 +221,16 @@ export class StellarWalletsKit implements KitActions {
221221

222222
this.buttonElement.remove();
223223
delete this.buttonElement;
224-
}
224+
};
225225
// ---- END Button methods
226226

227227
// ---- Modal methods
228-
public async openModal(params: {
228+
public openModal = async (params: {
229229
onWalletSelected: (option: ISupportedWallet) => void;
230230
onClosed?: (err: Error) => void;
231231
modalTitle?: string;
232232
notAvailableText?: string;
233-
}): Promise<void> {
233+
}): Promise<void> => {
234234
if (this.modalElement && !this.buttonElement) {
235235
throw new Error(`Stellar Wallets Kit modal is already open`);
236236
} else {
@@ -281,6 +281,6 @@ export class StellarWalletsKit implements KitActions {
281281
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
282282
// @ts-ignore
283283
this.modalElement.addEventListener('modal-closed', errorListener, false);
284-
}
284+
};
285285
// ---- END Modal methods
286286
}

0 commit comments

Comments
 (0)