@polkahub/proxy 0.2.2 → 0.3.1

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.
@@ -0,0 +1,202 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import { useModalContext, usePlugin, usePolkaHubContext, useAvailableAccounts, AddressIdentity } from '@polkahub/context';
3
+ import { defaultSerialize } from '@polkahub/plugin';
4
+ import { InlineAddressInput, Input, Button, AlertBox, AccountPicker } from '@polkahub/ui-components';
5
+ import { AccountId } from 'polkadot-api';
6
+ import { toHex } from 'polkadot-api/utils';
7
+ import { useState, useMemo, useEffect } from 'react';
8
+ import { proxyProviderId } from './provider.js';
9
+
10
+ const proxyTypeText = {
11
+ AssetManager: "Asset Manager",
12
+ AssetOwner: "Asset Owner",
13
+ CancelProxy: "Cancel Proxy",
14
+ NominationPools: "Nomination Pools",
15
+ NonTransfer: "Non-Transfer",
16
+ ParaRegistration: "Para Registration"
17
+ };
18
+ const AddProxy = ({ blockLength }) => {
19
+ const { popContent } = useModalContext();
20
+ const proxyProvider = usePlugin(proxyProviderId);
21
+ const { polkaHub } = usePolkaHubContext();
22
+ const [proxyAddress, setProxyAddress] = useState(null);
23
+ const [name, setName] = useState("");
24
+ const [selectedAccount, setSelectedAccount] = useState(null);
25
+ return /* @__PURE__ */ jsxs(
26
+ "form",
27
+ {
28
+ className: "space-y-2",
29
+ onSubmit: (evt) => {
30
+ evt.preventDefault();
31
+ if (!proxyAddress || !selectedAccount) return null;
32
+ const plugins = polkaHub.plugins$.getValue();
33
+ const parentProvider = plugins.find(
34
+ (p) => p.id === selectedAccount.provider
35
+ );
36
+ if (!parentProvider)
37
+ throw new Error(
38
+ `Parent provider ${selectedAccount.provider} not found`
39
+ );
40
+ const serializeFn = parentProvider.serialize ?? defaultSerialize;
41
+ proxyProvider?.addProxy({
42
+ real: proxyAddress,
43
+ parentSigner: serializeFn(selectedAccount),
44
+ name: name.trim() ? name.trim() : void 0
45
+ });
46
+ popContent();
47
+ },
48
+ children: [
49
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
50
+ /* @__PURE__ */ jsx("h3", { className: "font-medium text-muted-foreground", children: "Insert Proxy Address (Delegator)" }),
51
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
52
+ /* @__PURE__ */ jsx(
53
+ InlineAddressInput,
54
+ {
55
+ value: proxyAddress,
56
+ onChange: setProxyAddress,
57
+ className: "max-w-auto shrink-[2]"
58
+ }
59
+ ),
60
+ /* @__PURE__ */ jsx(
61
+ Input,
62
+ {
63
+ name: "account-name",
64
+ value: name,
65
+ onChange: (evt) => setName(evt.target.value),
66
+ placeholder: "Name (optional)",
67
+ className: "shrink-[3]"
68
+ }
69
+ )
70
+ ] })
71
+ ] }),
72
+ proxyAddress ? /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
73
+ /* @__PURE__ */ jsx("h3", { className: "font-medium text-muted-foreground", children: "Select your signer (Delegate)" }),
74
+ /* @__PURE__ */ jsx(
75
+ ProxySignerPicker,
76
+ {
77
+ value: selectedAccount,
78
+ onChange: setSelectedAccount,
79
+ proxy: proxyAddress
80
+ }
81
+ )
82
+ ] }) : null,
83
+ selectedAccount?.delegate ? /* @__PURE__ */ jsxs("div", { children: [
84
+ /* @__PURE__ */ jsx("h3", { className: "font-medium text-muted-foreground", children: "Permissions" }),
85
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-wrap gap-2", children: selectedAccount.delegate.map((entry, i) => /* @__PURE__ */ jsxs("li", { className: "border rounded px-2 py-1", children: [
86
+ proxyTypeText[entry.proxy_type.type] ?? entry.proxy_type.type,
87
+ entry.delay ? ` (${getDelayLength(entry.delay, blockLength)})` : ""
88
+ ] }, i)) })
89
+ ] }) : null,
90
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(Button, { disabled: !proxyAddress || !selectedAccount, children: "Add Proxy" }) })
91
+ ]
92
+ }
93
+ );
94
+ };
95
+ const getDelayLength = (blocks, blockLength) => {
96
+ if (!blockLength) return `delay ${blocks}`;
97
+ const seconds = blocks * blockLength / 1e3;
98
+ if (seconds < 120) {
99
+ return `${Math.round(seconds)}s delay`;
100
+ }
101
+ const minutes = Math.round(seconds / 60);
102
+ const min = minutes % 60;
103
+ const hours = Math.floor(minutes / 60);
104
+ const hr = hours % 24;
105
+ const days = Math.floor(hours / 24);
106
+ const time = `${hr}:${min.toString().padStart(2, "0")} delay`;
107
+ if (!days) {
108
+ return time;
109
+ }
110
+ return `${days}d ${time}`;
111
+ };
112
+ const useAsync = (fn, deps) => {
113
+ const [value, setValue] = useState({
114
+ type: "loading"
115
+ });
116
+ useEffect(() => {
117
+ let cancelled = false;
118
+ setValue({ type: "loading" });
119
+ fn().then(
120
+ (value2) => {
121
+ if (cancelled) return;
122
+ setValue({ type: "result", value: value2 });
123
+ },
124
+ (ex) => {
125
+ if (cancelled) return;
126
+ console.error(ex);
127
+ setValue({ type: "error" });
128
+ }
129
+ );
130
+ return () => {
131
+ cancelled = true;
132
+ };
133
+ }, deps);
134
+ return value;
135
+ };
136
+ const ProxySignerPicker = ({ value, onChange, proxy }) => {
137
+ const proxyProvider = usePlugin(proxyProviderId);
138
+ const availableAccounts = useAvailableAccounts();
139
+ const delegatesResult = useAsync(
140
+ () => proxyProvider.getDelegates(proxy),
141
+ [proxy]
142
+ );
143
+ const availableSigners = useMemo(
144
+ () => Object.entries(availableAccounts).map(([name, accounts]) => ({
145
+ name,
146
+ accounts: accounts.filter((acc) => !!acc.signer)
147
+ })).filter(({ accounts }) => accounts.length > 0),
148
+ [availableAccounts]
149
+ );
150
+ const selectableSigners = useMemo(() => {
151
+ if (delegatesResult.type === "loading") return null;
152
+ if (delegatesResult.value == null) return availableSigners;
153
+ const delegates = delegatesResult.value.reduce(
154
+ (acc, delegate) => {
155
+ const commonAddr = addrToCommon(delegate.delegate);
156
+ acc[commonAddr] ?? (acc[commonAddr] = []);
157
+ acc[commonAddr].push(delegate);
158
+ return acc;
159
+ },
160
+ {}
161
+ );
162
+ return availableSigners.map(({ name, accounts }) => ({
163
+ name,
164
+ accounts: accounts.map((account) => {
165
+ const delegate = delegates[addrToCommon(account.address)];
166
+ if (!delegate) return null;
167
+ return {
168
+ ...account,
169
+ delegate
170
+ };
171
+ }).filter((v) => v != null)
172
+ })).filter(({ accounts }) => accounts.length > 0);
173
+ }, [delegatesResult, availableSigners]);
174
+ if (selectableSigners == null) return /* @__PURE__ */ jsx("div", { children: "Loading\u2026" });
175
+ if (selectableSigners.length === 0 && delegatesResult.type === "result" && delegatesResult.value) {
176
+ const reason = delegatesResult.value.length === 0 ? `This account doesn't appear to be a proxy.` : `None of your connected signers are recognized as delegates of this proxy. Please configure the real signer account and try again`;
177
+ return /* @__PURE__ */ jsx(AlertBox, { variant: "error", children: reason });
178
+ }
179
+ return /* @__PURE__ */ jsx(
180
+ AccountPicker,
181
+ {
182
+ value,
183
+ onChange,
184
+ groups: selectableSigners,
185
+ className: "max-w-auto",
186
+ disableClear: true,
187
+ renderAddress: (account) => /* @__PURE__ */ jsx(
188
+ AddressIdentity,
189
+ {
190
+ addr: account.address,
191
+ name: account?.name,
192
+ copyable: false
193
+ }
194
+ )
195
+ }
196
+ );
197
+ };
198
+ const [ss58ToBin] = AccountId();
199
+ const addrToCommon = (addr) => addr.startsWith("0x") ? "0x" : toHex(ss58ToBin(addr));
200
+
201
+ export { AddProxy };
202
+ //# sourceMappingURL=AddProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddProxy.js","sources":["../src/AddProxy.tsx"],"sourcesContent":["import {\n AddressIdentity,\n useAvailableAccounts,\n useModalContext,\n usePlugin,\n usePolkaHubContext,\n} from \"@polkahub/context\";\nimport { Account, AccountAddress, defaultSerialize } from \"@polkahub/plugin\";\nimport {\n AccountPicker,\n AlertBox,\n Button,\n InlineAddressInput,\n Input,\n} from \"@polkahub/ui-components\";\nimport { AccountId } from \"polkadot-api\";\nimport { toHex } from \"polkadot-api/utils\";\nimport { useEffect, useMemo, useState, type FC } from \"react\";\nimport { ProxyEntry, ProxyProvider, proxyProviderId } from \"./provider\";\n\nconst proxyTypeText: Record<string, string | undefined> = {\n AssetManager: \"Asset Manager\",\n AssetOwner: \"Asset Owner\",\n CancelProxy: \"Cancel Proxy\",\n NominationPools: \"Nomination Pools\",\n NonTransfer: \"Non-Transfer\",\n ParaRegistration: \"Para Registration\",\n};\n\nexport type AddProxyProps = {\n blockLength?: number;\n};\n\nexport const AddProxy: FC<AddProxyProps> = ({ blockLength }) => {\n const { popContent } = useModalContext();\n const proxyProvider = usePlugin<ProxyProvider>(proxyProviderId);\n const { polkaHub } = usePolkaHubContext();\n\n const [proxyAddress, setProxyAddress] = useState<AccountAddress | null>(null);\n const [name, setName] = useState(\"\");\n const [selectedAccount, setSelectedAccount] =\n useState<AccountWithProxy | null>(null);\n\n return (\n <form\n className=\"space-y-2\"\n onSubmit={(evt) => {\n evt.preventDefault();\n if (!proxyAddress || !selectedAccount) return null;\n\n const plugins = polkaHub.plugins$.getValue();\n const parentProvider = plugins.find(\n (p) => p.id === selectedAccount.provider\n );\n if (!parentProvider)\n throw new Error(\n `Parent provider ${selectedAccount.provider} not found`\n );\n\n const serializeFn = parentProvider.serialize ?? defaultSerialize;\n proxyProvider?.addProxy({\n real: proxyAddress,\n parentSigner: serializeFn(selectedAccount),\n name: name.trim() ? name.trim() : undefined,\n });\n\n popContent();\n }}\n >\n <div className=\"space-y-2\">\n <h3 className=\"font-medium text-muted-foreground\">\n Insert Proxy Address (Delegator)\n </h3>\n <div className=\"flex gap-2\">\n <InlineAddressInput\n value={proxyAddress}\n onChange={setProxyAddress}\n className=\"max-w-auto shrink-[2]\"\n />\n <Input\n name=\"account-name\"\n value={name}\n onChange={(evt) => setName(evt.target.value)}\n placeholder=\"Name (optional)\"\n className=\"shrink-[3]\"\n />\n </div>\n </div>\n {proxyAddress ? (\n <div className=\"space-y-2\">\n <h3 className=\"font-medium text-muted-foreground\">\n Select your signer (Delegate)\n </h3>\n <ProxySignerPicker\n value={selectedAccount}\n onChange={setSelectedAccount}\n proxy={proxyAddress}\n />\n </div>\n ) : null}\n {selectedAccount?.delegate ? (\n <div>\n <h3 className=\"font-medium text-muted-foreground\">Permissions</h3>\n <ul className=\"flex flex-wrap gap-2\">\n {selectedAccount.delegate.map((entry, i) => (\n <li key={i} className=\"border rounded px-2 py-1\">\n {proxyTypeText[entry.proxy_type.type] ?? entry.proxy_type.type}\n {entry.delay\n ? ` (${getDelayLength(entry.delay, blockLength)})`\n : \"\"}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n <div className=\"flex justify-end\">\n <Button disabled={!proxyAddress || !selectedAccount}>Add Proxy</Button>\n </div>\n </form>\n );\n};\n\nconst getDelayLength = (blocks: number, blockLength?: number) => {\n if (!blockLength) return `delay ${blocks}`;\n\n const seconds = (blocks * blockLength) / 1000;\n if (seconds < 120) {\n return `${Math.round(seconds)}s delay`;\n }\n const minutes = Math.round(seconds / 60);\n const min = minutes % 60;\n const hours = Math.floor(minutes / 60);\n const hr = hours % 24;\n const days = Math.floor(hours / 24);\n\n const time = `${hr}:${min.toString().padStart(2, \"0\")} delay`;\n if (!days) {\n return time;\n }\n return `${days}d ${time}`;\n};\n\nconst useAsync = <T,>(fn: () => Promise<T>, deps: unknown[]) => {\n const [value, setValue] = useState<\n | {\n type: \"loading\" | \"error\";\n value?: never;\n }\n | {\n type: \"result\";\n value: T;\n }\n >({\n type: \"loading\",\n });\n\n useEffect(() => {\n let cancelled = false;\n\n setValue({ type: \"loading\" });\n fn().then(\n (value) => {\n if (cancelled) return;\n setValue({ type: \"result\", value });\n },\n (ex) => {\n if (cancelled) return;\n console.error(ex);\n setValue({ type: \"error\" });\n }\n );\n\n return () => {\n cancelled = true;\n };\n }, deps);\n\n return value;\n};\n\ntype AccountWithProxy = Account & {\n delegate?: ProxyEntry[];\n};\n\nconst ProxySignerPicker: FC<{\n value: AccountWithProxy | null;\n onChange: (value: AccountWithProxy | null) => void;\n proxy: AccountAddress;\n}> = ({ value, onChange, proxy }) => {\n const proxyProvider = usePlugin<ProxyProvider>(proxyProviderId)!;\n const availableAccounts = useAvailableAccounts();\n const delegatesResult = useAsync(\n () => proxyProvider.getDelegates(proxy),\n [proxy]\n );\n const availableSigners = useMemo(\n () =>\n Object.entries(availableAccounts)\n .map(([name, accounts]) => ({\n name,\n accounts: accounts.filter((acc) => !!acc.signer),\n }))\n .filter(({ accounts }) => accounts.length > 0),\n [availableAccounts]\n );\n\n const selectableSigners = useMemo(() => {\n if (delegatesResult.type === \"loading\") return null;\n if (delegatesResult.value == null) return availableSigners;\n\n const delegates = delegatesResult.value.reduce(\n (acc: Record<string, ProxyEntry[]>, delegate) => {\n const commonAddr = addrToCommon(delegate.delegate);\n acc[commonAddr] ??= [];\n acc[commonAddr].push(delegate);\n return acc;\n },\n {}\n );\n\n return availableSigners\n .map(({ name, accounts }) => ({\n name,\n accounts: accounts\n .map((account): AccountWithProxy | null => {\n const delegate = delegates[addrToCommon(account.address)];\n if (!delegate) return null;\n return {\n ...account,\n delegate,\n };\n })\n .filter((v) => v != null),\n }))\n .filter(({ accounts }) => accounts.length > 0);\n }, [delegatesResult, availableSigners]);\n\n if (selectableSigners == null) return <div>Loading…</div>;\n\n if (\n selectableSigners.length === 0 &&\n delegatesResult.type === \"result\" &&\n delegatesResult.value\n ) {\n const reason =\n delegatesResult.value.length === 0\n ? `This account doesn't appear to be a proxy.`\n : `None of your connected signers are recognized as delegates of this proxy. Please configure the real signer account and try again`;\n\n return <AlertBox variant=\"error\">{reason}</AlertBox>;\n }\n\n return (\n <AccountPicker\n value={value}\n onChange={onChange}\n groups={selectableSigners}\n className=\"max-w-auto\"\n disableClear\n renderAddress={(account) => (\n <AddressIdentity\n addr={account.address}\n name={account?.name}\n copyable={false}\n />\n )}\n />\n );\n};\n\nconst [ss58ToBin] = AccountId();\nconst addrToCommon = (addr: AccountAddress) =>\n addr.startsWith(\"0x\") ? \"0x\" : toHex(ss58ToBin(addr));\n"],"names":["value"],"mappings":"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"}
@@ -0,0 +1,76 @@
1
+ import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { ModalContext, usePlugin, useModalContext, AddressIdentity, AddressBalance } from '@polkahub/context';
3
+ import { useSetSelectedAccount } from '@polkahub/select-account';
4
+ import { SourceButton, Button } from '@polkahub/ui-components';
5
+ import { useStateObservable } from '@react-rxjs/core';
6
+ import { UserLock, Trash2 } from 'lucide-react';
7
+ import { useContext } from 'react';
8
+ import { AddProxy } from './AddProxy.js';
9
+ import { proxyProviderId } from './provider.js';
10
+
11
+ const ManageProxy = () => {
12
+ const { pushContent } = useContext(ModalContext);
13
+ const proxyProvider = usePlugin(proxyProviderId);
14
+ return /* @__PURE__ */ jsx(
15
+ SourceButton,
16
+ {
17
+ label: "Proxy",
18
+ onClick: () => pushContent({
19
+ title: "Proxied accounts",
20
+ element: /* @__PURE__ */ jsx(ManageAddresses, {})
21
+ }),
22
+ disabled: !proxyProvider,
23
+ children: /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(UserLock, { className: "size-10" }) })
24
+ }
25
+ );
26
+ };
27
+ const ManageAddresses = (props) => {
28
+ const { pushContent } = useModalContext();
29
+ const proxyProvider = usePlugin(proxyProviderId);
30
+ const proxyAccounts = useStateObservable(proxyProvider.accounts$);
31
+ const setAccount = useSetSelectedAccount();
32
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
33
+ proxyAccounts.length ? /* @__PURE__ */ jsxs("div", { children: [
34
+ /* @__PURE__ */ jsx("h3", { className: "font-medium text-muted-foreground", children: "Added addresses" }),
35
+ /* @__PURE__ */ jsx("ul", { className: "space-y-2", children: proxyAccounts.map((account, i) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2 items-center", children: [
36
+ /* @__PURE__ */ jsx(
37
+ Button,
38
+ {
39
+ variant: "outline",
40
+ className: "text-destructive",
41
+ type: "button",
42
+ onClick: () => proxyProvider.removeProxy(account.info),
43
+ children: /* @__PURE__ */ jsx(Trash2, {})
44
+ }
45
+ ),
46
+ /* @__PURE__ */ jsx(AddressIdentity, { addr: account.address }),
47
+ /* @__PURE__ */ jsx("div", { className: "grow" }),
48
+ /* @__PURE__ */ jsx(AddressBalance, { addr: account.address }),
49
+ setAccount ? /* @__PURE__ */ jsx(
50
+ Button,
51
+ {
52
+ variant: "secondary",
53
+ onClick: () => {
54
+ setAccount(account);
55
+ },
56
+ children: "Select"
57
+ }
58
+ ) : null
59
+ ] }, i)) })
60
+ ] }) : null,
61
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
62
+ Button,
63
+ {
64
+ type: "button",
65
+ onClick: () => pushContent({
66
+ title: "Add Proxy",
67
+ element: /* @__PURE__ */ jsx(AddProxy, { ...props })
68
+ }),
69
+ children: "Add Proxy"
70
+ }
71
+ ) })
72
+ ] });
73
+ };
74
+
75
+ export { ManageProxy };
76
+ //# sourceMappingURL=ManageProxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManageProxy.js","sources":["../src/ManageProxy.tsx"],"sourcesContent":["import {\n AddressBalance,\n AddressIdentity,\n ModalContext,\n useModalContext,\n usePlugin,\n} from \"@polkahub/context\";\nimport { useSetSelectedAccount } from \"@polkahub/select-account\";\nimport { Button, SourceButton } from \"@polkahub/ui-components\";\nimport { useStateObservable } from \"@react-rxjs/core\";\nimport { Trash2, UserLock } from \"lucide-react\";\nimport { useContext, type FC } from \"react\";\nimport { AddProxy, AddProxyProps } from \"./AddProxy\";\nimport { ProxyProvider, proxyProviderId } from \"./provider\";\n\nexport const ManageProxy: FC = () => {\n const { pushContent } = useContext(ModalContext)!;\n const proxyProvider = usePlugin<ProxyProvider>(proxyProviderId);\n\n return (\n <SourceButton\n label=\"Proxy\"\n onClick={() =>\n pushContent({\n title: \"Proxied accounts\",\n element: <ManageAddresses />,\n })\n }\n disabled={!proxyProvider}\n >\n <div>\n <UserLock className=\"size-10\" />\n </div>\n </SourceButton>\n );\n};\n\nconst ManageAddresses: FC<AddProxyProps> = (props) => {\n const { pushContent } = useModalContext();\n const proxyProvider = usePlugin<ProxyProvider>(proxyProviderId)!;\n const proxyAccounts = useStateObservable(proxyProvider.accounts$);\n const setAccount = useSetSelectedAccount();\n\n return (\n <div className=\"space-y-4\">\n {proxyAccounts.length ? (\n <div>\n <h3 className=\"font-medium text-muted-foreground\">Added addresses</h3>\n <ul className=\"space-y-2\">\n {proxyAccounts.map((account, i) => (\n <li key={i} className=\"flex gap-2 items-center\">\n <Button\n variant=\"outline\"\n className=\"text-destructive\"\n type=\"button\"\n onClick={() => proxyProvider.removeProxy(account.info)}\n >\n <Trash2 />\n </Button>\n <AddressIdentity addr={account.address} />\n <div className=\"grow\" />\n <AddressBalance addr={account.address} />\n {setAccount ? (\n <Button\n variant=\"secondary\"\n onClick={() => {\n setAccount(account);\n }}\n >\n Select\n </Button>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n <div className=\"flex justify-end\">\n <Button\n type=\"button\"\n onClick={() =>\n pushContent({\n title: \"Add Proxy\",\n element: <AddProxy {...props} />,\n })\n }\n >\n Add Proxy\n </Button>\n </div>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
- export { createProxyProvider } from './provider.js';
1
+ export { createProxyProvider, proxyProviderId } from './provider.js';
2
+ export { ManageProxy } from './ManageProxy.js';
2
3
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
package/dist/provider.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { getProxySigner } from '@polkadot-api/meta-signers';
2
2
  import { localStorageProvider, persistedState, addrEq } from '@polkahub/plugin';
3
3
  import { state } from '@react-rxjs/core';
4
- import { BehaviorSubject, combineLatest, switchMap, map } from 'rxjs';
4
+ import { BehaviorSubject, combineLatest, switchMap, firstValueFrom, map, filter, timeout } from 'rxjs';
5
5
 
6
- const createProxyProvider = (opts) => {
6
+ const proxyProviderId = "proxy";
7
+ const createProxyProvider = (getDelegates, opts) => {
7
8
  const { persist } = {
8
9
  persist: localStorageProvider("proxies"),
9
10
  ...opts
@@ -14,28 +15,41 @@ const createProxyProvider = (opts) => {
14
15
  );
15
16
  const plugins$ = new BehaviorSubject([]);
16
17
  const getAccount = (info, parentSigner) => ({
17
- provider: "proxy",
18
+ provider: proxyProviderId,
18
19
  address: info.real,
19
- signer: getProxySigner(info, parentSigner),
20
+ signer: parentSigner ? getProxySigner(info, parentSigner) : void 0,
21
+ name: info.name,
20
22
  info
21
23
  });
22
24
  const proxyInfoToAccount = async (info) => {
23
- const plugins = plugins$.getValue();
24
- const plugin = plugins.find((p) => info.parentSigner?.provider === p.id);
25
- if (!plugin) return null;
26
- const parentSigner = await plugin.deserialize(info.parentSigner);
27
- if (!parentSigner?.signer) return null;
28
- return getAccount(info, parentSigner.signer);
25
+ try {
26
+ const plugin = await firstValueFrom(
27
+ plugins$.pipe(
28
+ map(
29
+ (plugins) => plugins.find((p) => info.parentSigner?.provider === p.id)
30
+ ),
31
+ filter((v) => v != null),
32
+ timeout({
33
+ first: 3e3
34
+ })
35
+ )
36
+ );
37
+ if (!plugin) return getAccount(info);
38
+ const parentSigner = await plugin.deserialize(info.parentSigner);
39
+ return getAccount(info, parentSigner?.signer);
40
+ } catch (ex) {
41
+ console.error(ex);
42
+ return getAccount(info);
43
+ }
29
44
  };
30
45
  const accounts$ = state(
31
46
  combineLatest([persistedAccounts$, plugins$]).pipe(
32
- switchMap(([accounts]) => Promise.all(accounts.map(proxyInfoToAccount))),
33
- map((v) => v.filter((v2) => v2 !== null))
47
+ switchMap(([accounts]) => Promise.all(accounts.map(proxyInfoToAccount)))
34
48
  ),
35
49
  []
36
50
  );
37
51
  return {
38
- id: "proxy",
52
+ id: proxyProviderId,
39
53
  deserialize: (account) => {
40
54
  const extra = account.extra;
41
55
  return proxyInfoToAccount(extra);
@@ -64,9 +78,10 @@ const createProxyProvider = (opts) => {
64
78
  (prev) => prev.filter(
65
79
  (v) => !(addrEq(v.real, proxy.real) && addrEq(v.parentSigner.address, proxy.parentSigner.address))
66
80
  )
67
- )
81
+ ),
82
+ getDelegates
68
83
  };
69
84
  };
70
85
 
71
- export { createProxyProvider };
86
+ export { createProxyProvider, proxyProviderId };
72
87
  //# sourceMappingURL=provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sources":["../src/provider.ts"],"sourcesContent":["import { getProxySigner } from \"@polkadot-api/meta-signers\";\nimport {\n Account,\n AccountAddress,\n addrEq,\n localStorageProvider,\n persistedState,\n PersistenceProvider,\n Plugin,\n SerializableAccount,\n} from \"@polkahub/plugin\";\nimport { DefaultedStateObservable, state } from \"@react-rxjs/core\";\nimport { PolkadotSigner } from \"polkadot-api\";\nimport { BehaviorSubject, combineLatest, map, switchMap } from \"rxjs\";\n\nexport interface ProxyInfo {\n real: AccountAddress;\n type?: {\n type: string;\n value?: unknown;\n };\n parentSigner: SerializableAccount;\n}\n\nexport interface ProxyAccount extends Account {\n provider: \"proxy\";\n info: ProxyInfo;\n}\n\nexport interface ProxyProvider extends Plugin<ProxyAccount> {\n id: \"proxy\";\n accounts$: DefaultedStateObservable<ProxyAccount[]>;\n\n setProxies: (proxies: ProxyInfo[]) => void;\n addProxy: (proxy: ProxyInfo) => Promise<ProxyAccount | null>;\n removeProxy: (proxy: ProxyInfo) => void;\n}\n\nexport const createProxyProvider = (\n opts?: Partial<{\n persist: PersistenceProvider;\n }>\n): ProxyProvider => {\n const { persist } = {\n persist: localStorageProvider(\"proxies\"),\n ...opts,\n };\n\n const [persistedAccounts$, setPersistedAccounts] = persistedState(\n persist,\n [] as ProxyInfo[]\n );\n const plugins$ = new BehaviorSubject<Plugin[]>([]);\n\n const getAccount = (\n info: ProxyInfo,\n parentSigner: PolkadotSigner\n ): ProxyAccount => ({\n provider: \"proxy\",\n address: info.real,\n signer: getProxySigner(info, parentSigner),\n info,\n });\n\n const proxyInfoToAccount = async (info: ProxyInfo) => {\n const plugins = plugins$.getValue();\n const plugin = plugins.find((p) => info.parentSigner?.provider === p.id);\n if (!plugin) return null;\n const parentSigner = await plugin.deserialize(info.parentSigner);\n if (!parentSigner?.signer) return null;\n return getAccount(info, parentSigner.signer);\n };\n\n const accounts$ = state(\n combineLatest([persistedAccounts$, plugins$]).pipe(\n switchMap(([accounts]) => Promise.all(accounts.map(proxyInfoToAccount))),\n map((v) => v.filter((v) => v !== null))\n ),\n []\n );\n\n return {\n id: \"proxy\",\n deserialize: (account) => {\n const extra = account.extra as ProxyInfo;\n return proxyInfoToAccount(extra);\n },\n serialize: ({ address, info, provider }) => ({\n address,\n provider,\n extra: info,\n }),\n eq: (a, b) =>\n addrEq(a.address, b.address) &&\n addrEq(a.info.parentSigner?.address, b.info.parentSigner?.address),\n accounts$,\n receiveContext: (ctx) => plugins$.next(ctx.plugins),\n subscription$: accounts$,\n setProxies: setPersistedAccounts,\n addProxy: (proxy) => {\n setPersistedAccounts((prev) => {\n if (\n prev.some(\n (v) =>\n addrEq(v.real, proxy.real) &&\n addrEq(v.parentSigner.address, proxy.parentSigner.address)\n )\n )\n return prev;\n return [...prev, proxy];\n });\n return proxyInfoToAccount(proxy);\n },\n removeProxy: (proxy) =>\n setPersistedAccounts((prev) =>\n prev.filter(\n (v) =>\n !(\n addrEq(v.real, proxy.real) &&\n addrEq(v.parentSigner.address, proxy.parentSigner.address)\n )\n )\n ),\n };\n};\n"],"names":["v"],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sources":["../src/provider.ts"],"sourcesContent":["import { getProxySigner } from \"@polkadot-api/meta-signers\";\nimport {\n Account,\n AccountAddress,\n addrEq,\n localStorageProvider,\n persistedState,\n PersistenceProvider,\n Plugin,\n SerializableAccount,\n} from \"@polkahub/plugin\";\nimport { DefaultedStateObservable, state } from \"@react-rxjs/core\";\nimport { PolkadotSigner } from \"polkadot-api\";\nimport {\n BehaviorSubject,\n combineLatest,\n filter,\n firstValueFrom,\n map,\n switchMap,\n timeout,\n} from \"rxjs\";\n\nexport interface ProxyInfo {\n real: AccountAddress;\n parentSigner: SerializableAccount;\n name?: string;\n}\n\nexport const proxyProviderId = \"proxy\";\nexport interface ProxyAccount extends Account {\n provider: \"proxy\";\n info: ProxyInfo;\n}\n\nexport type ProxyEntry = {\n delegate: AccountAddress;\n proxy_type: {\n type: string;\n };\n delay: number;\n};\n\nexport type GetDelegates = (\n address: AccountAddress\n) => Promise<Array<ProxyEntry> | null>;\n\nexport interface ProxyProvider extends Plugin<ProxyAccount> {\n id: \"proxy\";\n accounts$: DefaultedStateObservable<ProxyAccount[]>;\n\n setProxies: (proxies: ProxyInfo[]) => void;\n addProxy: (proxy: ProxyInfo) => Promise<ProxyAccount | null>;\n removeProxy: (proxy: ProxyInfo) => void;\n\n getDelegates: GetDelegates;\n}\n\nexport const createProxyProvider = (\n getDelegates: GetDelegates,\n opts?: Partial<{\n persist: PersistenceProvider;\n }>\n): ProxyProvider => {\n const { persist } = {\n persist: localStorageProvider(\"proxies\"),\n ...opts,\n };\n\n const [persistedAccounts$, setPersistedAccounts] = persistedState(\n persist,\n [] as ProxyInfo[]\n );\n const plugins$ = new BehaviorSubject<Plugin[]>([]);\n\n const getAccount = (\n info: ProxyInfo,\n parentSigner?: PolkadotSigner\n ): ProxyAccount => ({\n provider: proxyProviderId,\n address: info.real,\n signer: parentSigner ? getProxySigner(info, parentSigner) : undefined,\n name: info.name,\n info,\n });\n\n const proxyInfoToAccount = async (info: ProxyInfo) => {\n try {\n const plugin = await firstValueFrom(\n plugins$.pipe(\n map((plugins) =>\n plugins.find((p) => info.parentSigner?.provider === p.id)\n ),\n filter((v) => v != null),\n timeout({\n first: 3000,\n })\n )\n );\n\n if (!plugin) return getAccount(info);\n const parentSigner = await plugin.deserialize(info.parentSigner);\n return getAccount(info, parentSigner?.signer);\n } catch (ex) {\n console.error(ex);\n return getAccount(info);\n }\n };\n\n const accounts$ = state(\n combineLatest([persistedAccounts$, plugins$]).pipe(\n switchMap(([accounts]) => Promise.all(accounts.map(proxyInfoToAccount)))\n ),\n []\n );\n\n return {\n id: proxyProviderId,\n deserialize: (account) => {\n const extra = account.extra as ProxyInfo;\n return proxyInfoToAccount(extra);\n },\n serialize: ({ address, info, provider }) => ({\n address,\n provider,\n extra: info,\n }),\n eq: (a, b) =>\n addrEq(a.address, b.address) &&\n addrEq(a.info.parentSigner?.address, b.info.parentSigner?.address),\n accounts$,\n receiveContext: (ctx) => plugins$.next(ctx.plugins),\n subscription$: accounts$,\n setProxies: setPersistedAccounts,\n addProxy: (proxy) => {\n setPersistedAccounts((prev) => {\n if (\n prev.some(\n (v) =>\n addrEq(v.real, proxy.real) &&\n addrEq(v.parentSigner.address, proxy.parentSigner.address)\n )\n )\n return prev;\n return [...prev, proxy];\n });\n return proxyInfoToAccount(proxy);\n },\n removeProxy: (proxy) =>\n setPersistedAccounts((prev) =>\n prev.filter(\n (v) =>\n !(\n addrEq(v.real, proxy.real) &&\n addrEq(v.parentSigner.address, proxy.parentSigner.address)\n )\n )\n ),\n getDelegates,\n };\n};\n"],"names":[],"mappings":"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"}
@@ -1,28 +1,38 @@
1
1
  import { AccountAddress, SerializableAccount, Account, Plugin, PersistenceProvider } from '@polkahub/plugin';
2
2
  import { DefaultedStateObservable } from '@react-rxjs/core';
3
+ import { FC } from 'react';
3
4
 
4
5
  interface ProxyInfo {
5
6
  real: AccountAddress;
6
- type?: {
7
- type: string;
8
- value?: unknown;
9
- };
10
7
  parentSigner: SerializableAccount;
8
+ name?: string;
11
9
  }
10
+ declare const proxyProviderId = "proxy";
12
11
  interface ProxyAccount extends Account {
13
12
  provider: "proxy";
14
13
  info: ProxyInfo;
15
14
  }
15
+ type ProxyEntry = {
16
+ delegate: AccountAddress;
17
+ proxy_type: {
18
+ type: string;
19
+ };
20
+ delay: number;
21
+ };
22
+ type GetDelegates = (address: AccountAddress) => Promise<Array<ProxyEntry> | null>;
16
23
  interface ProxyProvider extends Plugin<ProxyAccount> {
17
24
  id: "proxy";
18
25
  accounts$: DefaultedStateObservable<ProxyAccount[]>;
19
26
  setProxies: (proxies: ProxyInfo[]) => void;
20
27
  addProxy: (proxy: ProxyInfo) => Promise<ProxyAccount | null>;
21
28
  removeProxy: (proxy: ProxyInfo) => void;
29
+ getDelegates: GetDelegates;
22
30
  }
23
- declare const createProxyProvider: (opts?: Partial<{
31
+ declare const createProxyProvider: (getDelegates: GetDelegates, opts?: Partial<{
24
32
  persist: PersistenceProvider;
25
33
  }>) => ProxyProvider;
26
34
 
27
- export { createProxyProvider };
28
- export type { ProxyAccount, ProxyInfo, ProxyProvider };
35
+ declare const ManageProxy: FC;
36
+
37
+ export { ManageProxy, createProxyProvider, proxyProviderId };
38
+ export type { GetDelegates, ProxyAccount, ProxyEntry, ProxyInfo, ProxyProvider };
package/index.css ADDED
@@ -0,0 +1,2 @@
1
+ @import "@polkahub/ui-components";
2
+ @source "./dist";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polkahub/proxy",
3
- "version": "0.2.2",
3
+ "version": "0.3.1",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "type": "module",
@@ -9,6 +9,7 @@
9
9
  "types": "./dist/src/index.d.ts",
10
10
  "module": "./dist/index.js",
11
11
  "import": "./dist/index.js",
12
+ "style": "./index.css",
12
13
  "default": "./dist/index.js"
13
14
  },
14
15
  "./package.json": "./package.json"
@@ -17,16 +18,22 @@
17
18
  "main": "./dist/index.js",
18
19
  "module": "./dist/index.js",
19
20
  "browser": "./dist/index.js",
21
+ "style": "./index.css",
20
22
  "files": [
21
- "dist"
23
+ "dist",
24
+ "index.css"
22
25
  ],
23
26
  "dependencies": {
24
27
  "@polkadot-api/meta-signers": "^0.1.17",
25
28
  "@react-rxjs/core": "^0.10.8",
26
29
  "@react-rxjs/utils": "^0.9.7",
27
- "polkadot-api": "^1.20.1",
30
+ "lucide-react": "^0.553.0",
31
+ "polkadot-api": "^1.20.2",
28
32
  "rxjs": "^7.8.2",
29
- "@polkahub/plugin": "0.2.2"
33
+ "@polkahub/context": "0.3.1",
34
+ "@polkahub/select-account": "0.3.1",
35
+ "@polkahub/ui-components": "0.3.1",
36
+ "@polkahub/plugin": "0.3.1"
30
37
  },
31
38
  "peerDependencies": {
32
39
  "@types/react": "^19.2.2",