Skip to content

Commit b409661

Browse files
committed
feat: make current address getters async
the current address was being set when connecting, and the case where it changed wasn't being covered. Now it is being retrieved from the node every time
1 parent 881db0d commit b409661

16 files changed

+112
-98
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"author": "Polymath Studios Inc.",
1010
"license": "ISC",
1111
"main": "dist/index.js",
12+
"browser": "dist/index.browser.js",
1213
"typings": "dist/index.d.ts",
1314
"files": [
1415
"dist/**/*"
@@ -48,7 +49,7 @@
4849
"@0x/subproviders": "^3.0.2",
4950
"@babel/polyfill": "^7.0.0",
5051
"@babel/runtime": "^7.2.0",
51-
"@polymathnetwork/contract-wrappers": "2.0.0-beta.7",
52+
"@polymathnetwork/contract-wrappers": "2.0.0-beta.20",
5253
"bluebird": "^3.5.5",
5354
"ethereum-address": "^0.0.4",
5455
"json-stable-stringify": "^1.0.1",

src/Context.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
import { Wallet } from './Wallet';
22
import { PolymathBase } from './PolymathBase';
3+
import { onAddressChange } from './browserUtils';
34

45
interface ConstructorParams {
56
contractWrappers: PolymathBase;
6-
accountAddress?: string;
7-
}
8-
9-
export interface ContextWithWallet extends Context {
10-
currentWallet: Wallet;
117
}
128

139
/**
@@ -19,15 +15,13 @@ export interface ContextWithWallet extends Context {
1915
export class Context {
2016
public contractWrappers: PolymathBase;
2117

22-
public currentWallet?: Wallet;
18+
public currentWallet: Wallet;
2319

2420
constructor(params: ConstructorParams) {
25-
const { contractWrappers, accountAddress } = params;
21+
const { contractWrappers } = params;
2622

2723
this.contractWrappers = contractWrappers;
2824

29-
if (accountAddress) {
30-
this.currentWallet = new Wallet({ address: accountAddress });
31-
}
25+
this.currentWallet = new Wallet({ address: () => contractWrappers.getAccount() });
3226
}
3327
}

src/Polymath.ts

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,31 @@ import {
88
import P from 'bluebird';
99
import { Context } from './Context';
1010
import { getInjectedProvider } from './browserUtils';
11-
import { PolymathNetworkParams, ErrorCode } from './types';
11+
import { ErrorCode } from './types';
1212
import { Erc20TokenBalance, SecurityToken, SecurityTokenReservation } from './entities';
1313
import { ReserveSecurityToken } from './procedures';
1414
import { PolymathError } from './PolymathError';
1515
import { PolymathBase } from './PolymathBase';
1616

17+
interface PolymathNetworkParams {
18+
polymathRegistryAddress: string;
19+
}
20+
21+
interface PolymathNetworkNodeParams extends PolymathNetworkParams {
22+
providerUrl: string;
23+
privateKey: string;
24+
}
25+
26+
interface ConnectParams extends PolymathNetworkParams {
27+
providerUrl?: string;
28+
privateKey?: string;
29+
}
30+
31+
interface Connect {
32+
(params: PolymathNetworkParams): Promise<Polymath>;
33+
(params: PolymathNetworkNodeParams): Promise<Polymath>;
34+
}
35+
1736
export class Polymath {
1837
public networkId: number = -1;
1938

@@ -27,18 +46,19 @@ export class Polymath {
2746

2847
private context: Context = {} as Context;
2948

30-
public connect = async ({
49+
public connect: Connect = async ({
3150
polymathRegistryAddress,
3251
providerUrl,
3352
privateKey,
34-
}: PolymathNetworkParams) => {
53+
}: ConnectParams) => {
3554
let provider: Provider;
3655
const providerEngine = new Web3ProviderEngine();
3756
const injectedProvider = await getInjectedProvider();
3857

3958
if (providerUrl && privateKey) {
4059
providerEngine.addProvider(new PrivateKeyWalletSubprovider(privateKey));
4160
providerEngine.addProvider(new RedundantSubprovider([new RPCSubprovider(providerUrl)]));
61+
providerEngine.start();
4262
provider = providerEngine;
4363
} else if (injectedProvider) {
4464
provider = injectedProvider;
@@ -54,11 +74,8 @@ export class Polymath {
5474

5575
this.contractWrappers = contractWrappers;
5676

57-
const account = await contractWrappers.getAccount();
58-
5977
this.context = new Context({
6078
contractWrappers,
61-
accountAddress: account,
6279
});
6380

6481
this.isConnected = true;
@@ -88,17 +105,12 @@ export class Polymath {
88105
const {
89106
context: { currentWallet, contractWrappers },
90107
} = this;
108+
91109
let owner: string;
92110
if (args) {
93111
({ owner } = args);
94-
} else if (currentWallet) {
95-
({ address: owner } = currentWallet);
96112
} else {
97-
throw new PolymathError({
98-
code: ErrorCode.FetcherValidationError,
99-
message:
100-
"No default account set. You must pass the token owner's private key to Polymath.connect()",
101-
});
113+
owner = await currentWallet.address();
102114
}
103115

104116
const symbols = await contractWrappers.securityTokenRegistry.getTickersByOwner({ owner });
@@ -159,17 +171,12 @@ export class Polymath {
159171
const {
160172
context: { currentWallet, contractWrappers },
161173
} = this;
174+
162175
let owner: string;
163176
if (args) {
164177
({ owner } = args);
165-
} else if (currentWallet) {
166-
({ address: owner } = currentWallet);
167178
} else {
168-
throw new PolymathError({
169-
code: ErrorCode.FetcherValidationError,
170-
message:
171-
"No default account set. You must pass the token owner's private key to Polymath.connect()",
172-
});
179+
owner = await currentWallet.address();
173180
}
174181

175182
const symbols = await contractWrappers.securityTokenRegistry.getTokensByOwner({ owner });
@@ -289,11 +296,11 @@ export class Polymath {
289296
};
290297

291298
/**
292-
* Returns the wallet address of the current user if it exists
299+
* Returns the wallet address of the current user
293300
*/
294-
public getCurrentAddress = () => {
301+
public getCurrentAddress = async () => {
295302
const { currentWallet } = this.context;
296303

297-
return currentWallet ? currentWallet.address : undefined;
304+
return currentWallet.address();
298305
};
299306
}

src/Wallet.ts

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
interface Args {
2-
address: string;
2+
address: () => Promise<string>;
33
}
44

5-
// TODO @RafaelVidaurre: Implement caching strategies and dedupe-ing transactions
65
export class Wallet {
7-
public address: string;
6+
public address: () => Promise<string>;
87

98
constructor({ address }: Args) {
109
this.address = address;
1110
}
12-
13-
public toString() {
14-
return this.address;
15-
}
1611
}

src/browserUtils.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,14 @@ interface WindowWithWeb3 extends ExtendedWindow {
4343
* Returns the browser support for Ethereum
4444
*/
4545
export function getBrowserSupport() {
46-
const win = window as ExtendedWindow;
47-
if (!win) {
46+
const isClient = typeof window !== 'undefined';
47+
48+
if (!isClient) {
4849
return BrowserSupport.None;
4950
}
51+
52+
const win = window as ExtendedWindow;
53+
5054
if (win.ethereum) {
5155
return BrowserSupport.MetamaskModern;
5256
}
@@ -71,10 +75,14 @@ function isUnsupported(obj: any): obj is ExtendedWindow {
7175
/* eslint-enable @typescript-eslint/no-unused-vars */
7276

7377
export async function getInjectedProvider(): Promise<Provider | undefined> {
74-
const win = (window as any) as ExtendedWindow | undefined;
75-
if (!win) {
78+
const isClient = typeof window !== 'undefined';
79+
80+
if (!isClient) {
7681
return undefined;
7782
}
83+
84+
const win = (window as any) as ExtendedWindow;
85+
7886
if (isModern(win)) {
7987
const injectedProvider = win.ethereum;
8088
try {

src/entities/SecurityToken/SubModule.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { SecurityToken } from './SecurityToken';
22
import { Context } from '../../Context';
33

44
export class SubModule {
5-
public securityToken: SecurityToken;
5+
protected securityToken: SecurityToken;
66

77
protected context: Context;
88

src/procedures/ApproveErc20.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export class ApproveErc20 extends Procedure<ApproveErc20ProcedureArgs> {
1313
const { amount, spender, tokenAddress } = this.args;
1414
const { contractWrappers, currentWallet } = this.context;
1515

16-
const { address: ownerAddress } = currentWallet;
16+
const ownerAddress = await currentWallet.address();
1717

1818
const { polyToken } = contractWrappers;
1919

src/procedures/ControllerTransfer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export class ControllerTransfer extends Procedure<ControllerTransferProcedureArg
5252

5353
const controller = await securityToken.controller();
5454

55-
const { address: account } = currentWallet;
55+
const account = await currentWallet.address();
5656

5757
if (account !== controller) {
5858
throw new PolymathError({

src/procedures/CreateSecurityToken.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,11 @@ export class CreateSecurityToken extends Procedure<
2727
} = context;
2828

2929
let wallet: string;
30-
const { address: currentAddress } = currentWallet;
3130

3231
if (treasuryWallet) {
3332
wallet = treasuryWallet;
3433
} else {
35-
wallet = currentAddress;
34+
wallet = await currentWallet.address();
3635
}
3736

3837
const [isAvailable, isRegisteredByCurrentIssuer, isLaunched] = await Promise.all([

src/procedures/Procedure.ts

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
PolyTransactionTag,
1010
} from '../types';
1111
import { TransactionQueue } from '../entities/TransactionQueue';
12-
import { Context, ContextWithWallet } from '../Context';
12+
import { Context } from '../Context';
1313
import { PostTransactionResolver } from '../PostTransactionResolver';
1414
import { PolymathError } from '../PolymathError';
1515
import { Entity } from '../entities';
@@ -29,23 +29,15 @@ export abstract class Procedure<
2929

3030
protected args: Args;
3131

32-
protected context: ContextWithWallet;
32+
protected context: Context;
3333

3434
protected caller: Caller;
3535

3636
private transactions: TransactionSpec[] = [];
3737

3838
constructor(args: Args, context: Context, caller: Caller) {
39-
if (!context.currentWallet) {
40-
throw new PolymathError({
41-
message:
42-
"No default account set. You must pass the token owner's private key to Polymath.connect()",
43-
code: ErrorCode.ProcedureValidationError,
44-
});
45-
}
46-
4739
this.args = args;
48-
this.context = context as ContextWithWallet;
40+
this.context = context;
4941
this.caller = caller;
5042
}
5143

@@ -75,14 +67,14 @@ export abstract class Procedure<
7567
* @param options.resolver An asynchronous callback used to provide runtime data after
7668
* the added transaction has finished successfully
7769
*/
78-
public addProcedure<A, R extends any = any>(
70+
public addProcedure = <A, R extends any = any>(
7971
Proc: ProcedureClass<A>,
8072
{
8173
resolver = (() => {}) as () => Promise<R>,
8274
}: {
8375
resolver?: (receipt: TransactionReceiptWithDecodedLogs) => Promise<R>;
8476
} = {}
85-
) {
77+
) => {
8678
return async (args: A) => {
8779
const postTransactionResolver = new PostTransactionResolver(resolver);
8880
const operation = new Proc(args, this.context);
@@ -105,7 +97,7 @@ export abstract class Procedure<
10597
this.transactions = [...this.transactions, ...transactions];
10698
return postTransactionResolver;
10799
};
108-
}
100+
};
109101

110102
/**
111103
* Appends a method into the TransactionQueue's queue. This defines
@@ -117,7 +109,7 @@ export abstract class Procedure<
117109
* @param options.resolver An asynchronous callback used to provide runtime data after
118110
* the added transaction has finished successfully
119111
*/
120-
public addTransaction<A, R extends any = any>(
112+
public addTransaction = <A, R extends any = any>(
121113
method: LowLevelMethod<A>,
122114
{
123115
tag,
@@ -126,7 +118,7 @@ export abstract class Procedure<
126118
tag?: PolyTransactionTag;
127119
resolver?: (receipt: TransactionReceiptWithDecodedLogs) => Promise<R>;
128120
} = {}
129-
) {
121+
) => {
130122
return async (args: MapMaybeResolver<A>) => {
131123
const postTransactionResolver = new PostTransactionResolver(resolver);
132124

@@ -141,7 +133,7 @@ export abstract class Procedure<
141133

142134
return postTransactionResolver;
143135
};
144-
}
136+
};
145137

146138
protected abstract prepareTransactions(): Promise<
147139
MaybeResolver<ReturnType | undefined> | undefined

0 commit comments

Comments
 (0)