@gatedpath/frontend-kit 0.2.2 → 0.2.4
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.
- package/README.md +45 -2
- package/dist/abi.d.ts +18 -0
- package/dist/abi.js +14 -0
- package/dist/checkRecipient.d.ts +73 -0
- package/dist/checkRecipient.js +118 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,6 +17,10 @@ For agents
|
|
|
17
17
|
table (`@gatedpath/agent-rules/failures`): NotEligible (with the credential state when you pass
|
|
18
18
|
one), a wallet rejection, a wrong chain, not enough RBNT. Show `plainWords` and `fix.link`, never
|
|
19
19
|
`error.message` alone; `kind: "unknown"` carries the error's own words in `raw`.
|
|
20
|
+
- Before a send, `checkRecipient(client, { recipient, chainId })` (or `useRecipientCheck(recipient)`)
|
|
21
|
+
answers what card 13's `RecipientGuard` will answer on chain: `ok`, a `verdict`, and `reasons`
|
|
22
|
+
with a sentence each. Show the sentences; never build the transaction while `ok` is false. It
|
|
23
|
+
means an address someone verified holds, not the right person.
|
|
20
24
|
- Build: `npm run build`. Tests: `npm test` (Vitest, jsdom, a mocked transport; no network).
|
|
21
25
|
```
|
|
22
26
|
|
|
@@ -133,12 +137,51 @@ The panel renders only on chain 31337. On 151 or 153 it renders nothing whatever
|
|
|
133
137
|
and the scaffold imports it only in the dev server behind a build-time constant, so a production
|
|
134
138
|
bundle carries none of it; the scaffolder's integration test builds one and checks.
|
|
135
139
|
|
|
140
|
+
## checkRecipient
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
import { useRecipientCheck } from '@gatedpath/frontend-kit';
|
|
144
|
+
|
|
145
|
+
const { check, isChecking, error } = useRecipientCheck(recipient, { allowContract });
|
|
146
|
+
// check: { ok, verdict, reasons: [{ kind, error, plainWords }], permission, chainId } | null
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
{isChecking && <p>Asking the network…</p>}
|
|
150
|
+
{check?.reasons.map((r) => <p key={r.kind}>{r.plainWords}</p>)}
|
|
151
|
+
<button disabled={!check?.ok} onClick={send}>Send through the guard</button>
|
|
152
|
+
</>
|
|
153
|
+
);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
A transfer that refuses to lose your money (card 13) goes through `RecipientGuard`, a contract
|
|
157
|
+
that asks the network whether the recipient has passed the identity gate on this chain and
|
|
158
|
+
refuses if not. `checkRecipient(client, { recipient, chainId, allowContract?, amount?, permission?,
|
|
159
|
+
registry? })` asks the same questions from the browser first, in the guard's order, so the page can
|
|
160
|
+
say no before it asks for a signature: the zero address (`ZeroRecipient`); code at the address,
|
|
161
|
+
which makes it a contract the guard refuses unless `allowContract` is true (`RecipientIsContract`;
|
|
162
|
+
a 23-byte EIP-7702 delegation is still a wallet); the bootstrap registry naming no permission
|
|
163
|
+
contract, or one with no code (`NoPermissionContract`); `permission.isAllowed` false
|
|
164
|
+
(`RecipientNotPermissioned`); and, when you pass `amount`, zero (`NothingToSend`). Each reason
|
|
165
|
+
carries the guard's error name and a sentence for the page. The permission contract is resolved
|
|
166
|
+
through the registry on every call, as the guard does, because its proxy admin has moved before;
|
|
167
|
+
pass `permission` to skip that when the page already holds it. `client` is a viem `PublicClient`
|
|
168
|
+
(`usePublicClient()` in wagmi); the call throws if the client is on another chain than `chainId`,
|
|
169
|
+
and an RPC failure is thrown, never turned into a verdict.
|
|
170
|
+
|
|
171
|
+
`useRecipientCheck(recipient, { chainId?, allowContract?, permission?, registry?, refreshInterval?,
|
|
172
|
+
enabled? })` runs it when a recipient is set, caches the answer under the chain id and the recipient
|
|
173
|
+
for 30 s, and exposes `refresh()`. The page's answer is a courtesy and the contract's is the rule:
|
|
174
|
+
`ok` means an address someone verified holds on this chain, or a contract the user said they mean.
|
|
175
|
+
A typo that lands on another verified address goes through, and the page should say so.
|
|
176
|
+
|
|
136
177
|
## Tests
|
|
137
178
|
|
|
138
|
-
`npm test`:
|
|
179
|
+
`npm test`: 122 Vitest tests in jsdom. `test/mock-chain.tsx` is a wagmi config over a `custom`
|
|
139
180
|
transport that answers `eth_chainId`, `eth_blockNumber`, `eth_call` and Multicall3 `aggregate3`
|
|
181
|
+
(and, since `checkRecipient`, `eth_getCode` and the bootstrap registry's `getContractAddress`)
|
|
140
182
|
from an in-memory state the tests mutate; nothing leaves the process and no address in it exists
|
|
141
|
-
anywhere.
|
|
183
|
+
anywhere. `test/checkRecipient.test.tsx` covers every refusal the guard makes, the ok path, the
|
|
184
|
+
EIP-7702 case, a given permission contract, the chain mismatch and the hook's cache and refresh. The hook tests cover every state, that reads happen once and then only on a new block,
|
|
142
185
|
manual refresh without a block, shared reads, the expiry window, errors and `enabled: false`. The
|
|
143
186
|
component tests render every state, the gate's selection and override, the links (Access dApp,
|
|
144
187
|
faucet, Vine) and the retry and refresh buttons. `test/dev-panel.test.tsx` runs the dev panel
|
package/dist/abi.d.ts
CHANGED
|
@@ -15,6 +15,24 @@ export declare const verifierAbi: readonly [{
|
|
|
15
15
|
readonly type: "bool";
|
|
16
16
|
}];
|
|
17
17
|
}];
|
|
18
|
+
/**
|
|
19
|
+
* The bootstrap registry, the one fixed address on both chains: `getContractAddress("permission")`
|
|
20
|
+
* names the permission contract. `checkRecipient` asks it on every call rather than remembering
|
|
21
|
+
* the answer, because the permission proxy's admin has moved before.
|
|
22
|
+
*/
|
|
23
|
+
export declare const bootstrapRegistryAbi: readonly [{
|
|
24
|
+
readonly type: "function";
|
|
25
|
+
readonly name: "getContractAddress";
|
|
26
|
+
readonly stateMutability: "view";
|
|
27
|
+
readonly inputs: readonly [{
|
|
28
|
+
readonly name: "name";
|
|
29
|
+
readonly type: "string";
|
|
30
|
+
}];
|
|
31
|
+
readonly outputs: readonly [{
|
|
32
|
+
readonly name: "";
|
|
33
|
+
readonly type: "address";
|
|
34
|
+
}];
|
|
35
|
+
}];
|
|
18
36
|
/** The network's permission contract: `isAllowed(address)` (RESEARCH.md question 7). */
|
|
19
37
|
export declare const permissionAbi: readonly [{
|
|
20
38
|
readonly type: "function";
|
package/dist/abi.js
CHANGED
|
@@ -12,6 +12,20 @@ export const verifierAbi = [
|
|
|
12
12
|
outputs: [{ name: '', type: 'bool' }],
|
|
13
13
|
},
|
|
14
14
|
];
|
|
15
|
+
/**
|
|
16
|
+
* The bootstrap registry, the one fixed address on both chains: `getContractAddress("permission")`
|
|
17
|
+
* names the permission contract. `checkRecipient` asks it on every call rather than remembering
|
|
18
|
+
* the answer, because the permission proxy's admin has moved before.
|
|
19
|
+
*/
|
|
20
|
+
export const bootstrapRegistryAbi = [
|
|
21
|
+
{
|
|
22
|
+
type: 'function',
|
|
23
|
+
name: 'getContractAddress',
|
|
24
|
+
stateMutability: 'view',
|
|
25
|
+
inputs: [{ name: 'name', type: 'string' }],
|
|
26
|
+
outputs: [{ name: '', type: 'address' }],
|
|
27
|
+
},
|
|
28
|
+
];
|
|
15
29
|
/** The network's permission contract: `isAllowed(address)` (RESEARCH.md question 7). */
|
|
16
30
|
export const permissionAbi = [
|
|
17
31
|
{
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PublicClient } from 'viem';
|
|
2
|
+
import type { Address } from './useEligibility.js';
|
|
3
|
+
/** `RecipientGuard.Verdict`, plus the one case where the guard cannot reach a verdict at all. */
|
|
4
|
+
export type RecipientVerdict = 'permissioned' | 'not-permissioned' | 'contract' | 'zero' | 'no-permission-contract';
|
|
5
|
+
/** One per named revert in `RecipientGuard`, except `NativeTransferFailed`, which only the send itself can find. */
|
|
6
|
+
export type RecipientReasonKind = 'zero-recipient' | 'recipient-is-contract' | 'recipient-not-permissioned' | 'no-permission-contract' | 'nothing-to-send';
|
|
7
|
+
export interface RecipientReason {
|
|
8
|
+
kind: RecipientReasonKind;
|
|
9
|
+
/** The guard's error name for this refusal, as a block explorer or `explainError` would show it. */
|
|
10
|
+
error: 'ZeroRecipient' | 'RecipientIsContract' | 'RecipientNotPermissioned' | 'NoPermissionContract' | 'NothingToSend';
|
|
11
|
+
/** A sentence for the page. */
|
|
12
|
+
plainWords: string;
|
|
13
|
+
}
|
|
14
|
+
export interface CheckRecipientOptions {
|
|
15
|
+
recipient: Address;
|
|
16
|
+
/** The chain the client reads. Refused when the client says it is on a different one. */
|
|
17
|
+
chainId: number;
|
|
18
|
+
/** True when the user has said a contract is what they mean to pay (`send(to, allowContract)`). Default false. */
|
|
19
|
+
allowContract?: boolean;
|
|
20
|
+
/** The amount about to be sent, when known; zero is refused the way `send` refuses an empty call. */
|
|
21
|
+
amount?: bigint;
|
|
22
|
+
/** Skip the registry and read this permission contract. Default: resolve it live, as the guard does. */
|
|
23
|
+
permission?: Address;
|
|
24
|
+
/** The bootstrap registry. Default: the shared address from @gatedpath/chains. */
|
|
25
|
+
registry?: Address;
|
|
26
|
+
}
|
|
27
|
+
export interface RecipientCheck {
|
|
28
|
+
/** True when the guard would let the send through to this recipient. */
|
|
29
|
+
ok: boolean;
|
|
30
|
+
verdict: RecipientVerdict;
|
|
31
|
+
/** Empty when `ok`. Otherwise every refusal the guard would raise, in the order it raises them. */
|
|
32
|
+
reasons: RecipientReason[];
|
|
33
|
+
recipient: Address;
|
|
34
|
+
chainId: number;
|
|
35
|
+
/** The permission contract the answer came from, when one was read. */
|
|
36
|
+
permission: Address | null;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Asks the network what `RecipientGuard.check(to)` would answer, and turns it into the refusals
|
|
40
|
+
* `send` would raise. Reads, in the guard's order: the recipient's code; then, for a wallet, the
|
|
41
|
+
* registry's code, the permission contract it names, that contract's code, and `isAllowed`. The
|
|
42
|
+
* permission contract is resolved on every call and never remembered, because its proxy admin has
|
|
43
|
+
* moved before (14 September 2026); pass `permission` to skip that when the page already knows it.
|
|
44
|
+
*
|
|
45
|
+
* What `ok` means: an address someone verified holds on this chain, or a contract the user has
|
|
46
|
+
* said they mean. It does not mean the right person: a typo that lands on another verified
|
|
47
|
+
* address goes through. Say that on the page.
|
|
48
|
+
*/
|
|
49
|
+
export declare function checkRecipient(client: PublicClient, options: CheckRecipientOptions): Promise<RecipientCheck>;
|
|
50
|
+
export interface UseRecipientCheckOptions {
|
|
51
|
+
/** Chain to read on. Defaults to wagmi's current chain. */
|
|
52
|
+
chainId?: number;
|
|
53
|
+
allowContract?: boolean;
|
|
54
|
+
permission?: Address;
|
|
55
|
+
registry?: Address;
|
|
56
|
+
/** How long an answer is kept before the next render reads again. Default 30 000 ms. */
|
|
57
|
+
refreshInterval?: number;
|
|
58
|
+
enabled?: boolean;
|
|
59
|
+
}
|
|
60
|
+
export interface RecipientCheckResult {
|
|
61
|
+
/** The last answer, or null before the first one. */
|
|
62
|
+
check: RecipientCheck | null;
|
|
63
|
+
isChecking: boolean;
|
|
64
|
+
error: Error | null;
|
|
65
|
+
/** Read again now. */
|
|
66
|
+
refresh: () => Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* `checkRecipient` as a hook: runs when `recipient` is set, caches the answer under the chain id
|
|
70
|
+
* and the recipient for `refreshInterval`, and reads again on `refresh()`. Mount it on the
|
|
71
|
+
* recipient field; show `check.reasons[*].plainWords` under it.
|
|
72
|
+
*/
|
|
73
|
+
export declare function useRecipientCheck(recipient: Address | undefined, options?: UseRecipientCheckOptions): RecipientCheckResult;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
// checkRecipient: the question card 13's RecipientGuard asks on chain, asked from the browser
|
|
3
|
+
// first, so a page can refuse before it asks for a signature. Same reads, same order, same
|
|
4
|
+
// answers as `RecipientGuard.check` and `_requirePasses`; the contract's answer is still the rule
|
|
5
|
+
// and this one is the courtesy. No cache here: `useRecipientCheck` caches per chain so an answer
|
|
6
|
+
// from 153 is never shown for 151.
|
|
7
|
+
import { useCallback, useMemo } from 'react';
|
|
8
|
+
import { useQuery } from '@tanstack/react-query';
|
|
9
|
+
import { useChainId, usePublicClient } from 'wagmi';
|
|
10
|
+
import { addresses, chainById } from '@gatedpath/chains';
|
|
11
|
+
import { bootstrapRegistryAbi, permissionAbi } from './abi.js';
|
|
12
|
+
const ZERO = '0x0000000000000000000000000000000000000000';
|
|
13
|
+
const WORDS = {
|
|
14
|
+
'zero-recipient': {
|
|
15
|
+
error: 'ZeroRecipient',
|
|
16
|
+
plainWords: 'That is the zero address. Nothing can be sent there, and the guard refuses it.',
|
|
17
|
+
},
|
|
18
|
+
'recipient-is-contract': {
|
|
19
|
+
error: 'RecipientIsContract',
|
|
20
|
+
plainWords: 'This is a contract, not a wallet, so it has never been through the identity gate. The guard refuses it unless you say a contract is what you mean to pay.',
|
|
21
|
+
},
|
|
22
|
+
'recipient-not-permissioned': {
|
|
23
|
+
error: 'RecipientNotPermissioned',
|
|
24
|
+
plainWords: 'No one verified holds this address on this chain. Money sent there would be gone, so the guard refuses.',
|
|
25
|
+
},
|
|
26
|
+
'no-permission-contract': {
|
|
27
|
+
error: 'NoPermissionContract',
|
|
28
|
+
plainWords: 'This chain has no permission contract behind its registry, so there is nothing to check a recipient against. The guard refuses every send here.',
|
|
29
|
+
},
|
|
30
|
+
'nothing-to-send': {
|
|
31
|
+
error: 'NothingToSend',
|
|
32
|
+
plainWords: 'The amount is zero. There is nothing to send.',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
function reason(kind) {
|
|
36
|
+
return { kind, ...WORDS[kind] };
|
|
37
|
+
}
|
|
38
|
+
/** `RecipientGuard._isContract`: code at the address, unless it is an EIP-7702 delegation designator, which is still a wallet. */
|
|
39
|
+
function isContractCode(code) {
|
|
40
|
+
if (!code || code === '0x')
|
|
41
|
+
return false;
|
|
42
|
+
const bytes = (code.length - 2) / 2;
|
|
43
|
+
return !(bytes === 23 && code.toLowerCase().startsWith('0xef0100'));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Asks the network what `RecipientGuard.check(to)` would answer, and turns it into the refusals
|
|
47
|
+
* `send` would raise. Reads, in the guard's order: the recipient's code; then, for a wallet, the
|
|
48
|
+
* registry's code, the permission contract it names, that contract's code, and `isAllowed`. The
|
|
49
|
+
* permission contract is resolved on every call and never remembered, because its proxy admin has
|
|
50
|
+
* moved before (14 September 2026); pass `permission` to skip that when the page already knows it.
|
|
51
|
+
*
|
|
52
|
+
* What `ok` means: an address someone verified holds on this chain, or a contract the user has
|
|
53
|
+
* said they mean. It does not mean the right person: a typo that lands on another verified
|
|
54
|
+
* address goes through. Say that on the page.
|
|
55
|
+
*/
|
|
56
|
+
export async function checkRecipient(client, options) {
|
|
57
|
+
const { recipient, chainId } = options;
|
|
58
|
+
if (client.chain && client.chain.id !== chainId) {
|
|
59
|
+
throw new Error(`checkRecipient: the client is on chain ${client.chain.id}, not ${chainId}; an answer from one chain is never shown for another`);
|
|
60
|
+
}
|
|
61
|
+
const reasons = [];
|
|
62
|
+
if (options.amount !== undefined && options.amount === 0n)
|
|
63
|
+
reasons.push(reason('nothing-to-send'));
|
|
64
|
+
const base = { recipient, chainId, permission: null };
|
|
65
|
+
if (recipient.toLowerCase() === ZERO) {
|
|
66
|
+
reasons.push(reason('zero-recipient'));
|
|
67
|
+
return { ...base, ok: false, verdict: 'zero', reasons };
|
|
68
|
+
}
|
|
69
|
+
const code = await client.getCode({ address: recipient });
|
|
70
|
+
if (isContractCode(code)) {
|
|
71
|
+
if (!options.allowContract)
|
|
72
|
+
reasons.push(reason('recipient-is-contract'));
|
|
73
|
+
return { ...base, ok: reasons.length === 0, verdict: 'contract', reasons };
|
|
74
|
+
}
|
|
75
|
+
let permission = options.permission ?? null;
|
|
76
|
+
if (!permission) {
|
|
77
|
+
const registry = options.registry ?? chainById(chainId)?.contracts['bootstrapRegistry']?.address ?? addresses.mainnet.bootstrapRegistry.address;
|
|
78
|
+
const registryCode = await client.getCode({ address: registry });
|
|
79
|
+
const named = registryCode && registryCode !== '0x'
|
|
80
|
+
? await client.readContract({ address: registry, abi: bootstrapRegistryAbi, functionName: 'getContractAddress', args: ['permission'] })
|
|
81
|
+
: ZERO;
|
|
82
|
+
const permissionCode = named.toLowerCase() === ZERO ? '0x' : await client.getCode({ address: named });
|
|
83
|
+
if (!permissionCode || permissionCode === '0x') {
|
|
84
|
+
reasons.push(reason('no-permission-contract'));
|
|
85
|
+
return { ...base, ok: false, verdict: 'no-permission-contract', reasons };
|
|
86
|
+
}
|
|
87
|
+
permission = named;
|
|
88
|
+
}
|
|
89
|
+
const allowed = await client.readContract({ address: permission, abi: permissionAbi, functionName: 'isAllowed', args: [recipient] });
|
|
90
|
+
if (!allowed)
|
|
91
|
+
reasons.push(reason('recipient-not-permissioned'));
|
|
92
|
+
return { ...base, permission, ok: reasons.length === 0, verdict: allowed ? 'permissioned' : 'not-permissioned', reasons };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* `checkRecipient` as a hook: runs when `recipient` is set, caches the answer under the chain id
|
|
96
|
+
* and the recipient for `refreshInterval`, and reads again on `refresh()`. Mount it on the
|
|
97
|
+
* recipient field; show `check.reasons[*].plainWords` under it.
|
|
98
|
+
*/
|
|
99
|
+
export function useRecipientCheck(recipient, options = {}) {
|
|
100
|
+
const currentChainId = useChainId();
|
|
101
|
+
const chainId = options.chainId ?? currentChainId;
|
|
102
|
+
const client = usePublicClient({ chainId });
|
|
103
|
+
const allowContract = options.allowContract ?? false;
|
|
104
|
+
const enabled = (options.enabled ?? true) && Boolean(client && recipient);
|
|
105
|
+
const { permission, registry } = options;
|
|
106
|
+
const query = useQuery({
|
|
107
|
+
queryKey: ['redbelly-frontend-kit', 'recipient', chainId, recipient?.toLowerCase(), allowContract, permission, registry],
|
|
108
|
+
queryFn: () => checkRecipient(client, { recipient: recipient, chainId, allowContract, permission, registry }),
|
|
109
|
+
enabled,
|
|
110
|
+
staleTime: options.refreshInterval ?? 30_000,
|
|
111
|
+
refetchOnWindowFocus: false,
|
|
112
|
+
});
|
|
113
|
+
const refetch = query.refetch;
|
|
114
|
+
const refresh = useCallback(async () => {
|
|
115
|
+
await refetch();
|
|
116
|
+
}, [refetch]);
|
|
117
|
+
return useMemo(() => ({ check: query.data ?? null, isChecking: enabled && query.isPending, error: query.error ?? null, refresh }), [query.data, query.isPending, query.error, enabled, refresh]);
|
|
118
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,9 @@ export { receptorMockExpiry } from './expiry.js';
|
|
|
4
4
|
export { notifyEligibilityChanged, onEligibilityChanged } from './events.js';
|
|
5
5
|
export { EligibilityGate, NotConnected, NotVerified, Ineligible, Eligible, ExpiringSoon, Checking, EligibilityError, LastChecked, GasWarning, } from './components.js';
|
|
6
6
|
export type { EligibilityGateProps, StateProps, NotVerifiedProps, IneligibleProps, ExpiringSoonProps, EligibilityErrorProps, LastCheckedProps, GasWarningProps, } from './components.js';
|
|
7
|
-
export {
|
|
7
|
+
export { checkRecipient, useRecipientCheck } from './checkRecipient.js';
|
|
8
|
+
export type { RecipientCheck, RecipientReason, RecipientReasonKind, RecipientVerdict, CheckRecipientOptions, UseRecipientCheckOptions, RecipientCheckResult } from './checkRecipient.js';
|
|
9
|
+
export { verifierAbi, permissionAbi, bootstrapRegistryAbi, receptorMockAbi, receptorMockStatusAbi, registerTokenAbi, identityRegistryAbi, trustedIssuersRegistryAbi, claimTopicsRegistryAbi } from './abi.js';
|
|
8
10
|
export { useRegister } from './useRegister.js';
|
|
9
11
|
export type { RegisterState, RegisterResult, UseRegisterOptions } from './useRegister.js';
|
|
10
12
|
export { ACCESS_URL, FAUCET_URL, VINE_INTERACTION_URL, VINE_FEES_URL } from './urls.js';
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,8 @@ export { useEligibility } from './useEligibility.js';
|
|
|
2
2
|
export { receptorMockExpiry } from './expiry.js';
|
|
3
3
|
export { notifyEligibilityChanged, onEligibilityChanged } from './events.js';
|
|
4
4
|
export { EligibilityGate, NotConnected, NotVerified, Ineligible, Eligible, ExpiringSoon, Checking, EligibilityError, LastChecked, GasWarning, } from './components.js';
|
|
5
|
-
export {
|
|
5
|
+
export { checkRecipient, useRecipientCheck } from './checkRecipient.js';
|
|
6
|
+
export { verifierAbi, permissionAbi, bootstrapRegistryAbi, receptorMockAbi, receptorMockStatusAbi, registerTokenAbi, identityRegistryAbi, trustedIssuersRegistryAbi, claimTopicsRegistryAbi } from './abi.js';
|
|
6
7
|
export { useRegister } from './useRegister.js';
|
|
7
8
|
export { ACCESS_URL, FAUCET_URL, VINE_INTERACTION_URL, VINE_FEES_URL } from './urls.js';
|
|
8
9
|
export { explainError } from './explainError.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gatedpath/frontend-kit",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "React components and one hook for the five eligibility states every Redbelly dApp has: not connected, connected but not verified on the network, verified but ineligible for this action, eligible, credential expiring soon; plus explainError, the plain words for a viem or wagmi error from the shared failure table. wagmi + viem, headless with a small default style.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|