-
Notifications
You must be signed in to change notification settings - Fork 4
/
TurnkeyWalletContext.tsx
124 lines (106 loc) · 3.46 KB
/
TurnkeyWalletContext.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import { Eip1193Bridge } from "@ethersproject/experimental";
import { TurnkeySigner } from "@turnkey/ethers";
import { ethers } from "ethers";
import * as React from "react";
import { assertNonEmptyString } from "../utils";
import { useCredentialsContext } from "./CredentialsContext";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
// This is the list that Infura supports in Ethers v5
// https://github.com/ethers-io/ethers.js/blob/f97b92bbb1bde22fcc44100af78d7f31602863ab/packages/providers/src.ts/infura-provider.ts#L86
export const infuraNetworkList = [
"homestead",
"goerli",
"sepolia",
"matic",
"maticmum",
"optimism",
"optimism-goerli",
"arbitrum",
"arbitrum-goerli",
] as const;
export type TInfuraNetwork = (typeof infuraNetworkList)[number];
type TTurnkeyWalletContextValue = {
connectedSigner: TurnkeySigner | null;
eip1193: Eip1193Bridge | null;
network: TInfuraNetwork;
setNetwork: (x: TInfuraNetwork) => void;
error: Error | null;
} | null;
const TurnkeyWalletContext =
React.createContext<TTurnkeyWalletContextValue>(null);
export function TurnkeyWalletContextProvider(props: {
children: React.ReactNode;
}) {
const [network, setNetwork] = React.useState<TInfuraNetwork>("homestead");
const { credentials } = useCredentialsContext();
const {
TURNKEY_API_PUBLIC_KEY,
TURNKEY_API_PRIVATE_KEY,
TURNKEY_BASE_URL,
TURNKEY_ORGANIZATION_ID,
TURNKEY_PRIVATE_KEY_ID,
INFURA_API_KEY,
} = credentials;
const contextValue = React.useMemo(() => {
let connectedSigner: TurnkeySigner | null = null;
let eip1193: Eip1193Bridge | null = null;
let error: Error | null = null;
try {
assertNonEmptyString(TURNKEY_API_PUBLIC_KEY, "TURNKEY_API_PUBLIC_KEY");
assertNonEmptyString(TURNKEY_API_PRIVATE_KEY, "TURNKEY_API_PRIVATE_KEY");
assertNonEmptyString(TURNKEY_BASE_URL, "TURNKEY_BASE_URL");
assertNonEmptyString(TURNKEY_ORGANIZATION_ID, "TURNKEY_ORGANIZATION_ID");
assertNonEmptyString(TURNKEY_PRIVATE_KEY_ID, "TURNKEY_PRIVATE_KEY_ID");
const stamper = new ApiKeyStamper({
apiPublicKey: TURNKEY_API_PUBLIC_KEY,
apiPrivateKey: TURNKEY_API_PRIVATE_KEY,
});
const client = new TurnkeyClient({
baseUrl: TURNKEY_BASE_URL,
}, stamper)
const signer = new TurnkeySigner({
client: client,
organizationId: TURNKEY_ORGANIZATION_ID,
privateKeyId: TURNKEY_PRIVATE_KEY_ID,
});
const provider = new ethers.providers.InfuraProvider(
network,
INFURA_API_KEY
);
connectedSigner = signer.connect(provider);
eip1193 = new Eip1193Bridge(connectedSigner, provider);
} catch (e) {
error = e as Error;
}
return {
connectedSigner,
eip1193,
network,
setNetwork,
error,
};
}, [
INFURA_API_KEY,
TURNKEY_API_PRIVATE_KEY,
TURNKEY_API_PUBLIC_KEY,
TURNKEY_BASE_URL,
TURNKEY_ORGANIZATION_ID,
TURNKEY_PRIVATE_KEY_ID,
network,
]);
return (
<TurnkeyWalletContext.Provider value={contextValue}>
{props.children}
</TurnkeyWalletContext.Provider>
);
}
export function useTurnkeyWalletContext(): NonNullable<TTurnkeyWalletContextValue> {
const value = React.useContext(TurnkeyWalletContext);
if (value == null) {
throw new Error(
`Context wasn't initialized. Did you forget to put a \`<TurnkeyWalletContextProvider>\` ancestor?`
);
}
return value;
}