@txwallet/graz-connector 0.1.0
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 +205 -0
- package/index.d.ts +152 -0
- package/index.js +921 -0
- package/package.json +42 -0
- package/react.d.ts +47 -0
- package/react.js +106 -0
package/README.md
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# @txwallet/graz-connector
|
|
2
|
+
|
|
3
|
+
Thin-slice TX Wallet compatibility connector for Graz-oriented Cosmos integrations.
|
|
4
|
+
|
|
5
|
+
Ownership note: this package is an adapter layer. The TX Wallet Auth protocol remains the source of truth for request IDs, payload verification, callback policy, and approval outcomes.
|
|
6
|
+
|
|
7
|
+
This package is the first implementation rail only:
|
|
8
|
+
|
|
9
|
+
- connect
|
|
10
|
+
- account and chain context
|
|
11
|
+
- ADR-36 sign-in result path
|
|
12
|
+
- typed transaction-request launch path for approved payment lanes
|
|
13
|
+
|
|
14
|
+
It does not claim full Keplr or Leap parity.
|
|
15
|
+
|
|
16
|
+
Partner rollout checklist: see `TX_WALLET_GRAZ_PARTNER_QUICKSTART.md` in the repo root for the end-to-end thin-slice handoff flow.
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @txwallet/graz-connector
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Minimal usage
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { createTxWalletGrazConnector } from '@txwallet/graz-connector';
|
|
28
|
+
|
|
29
|
+
const connector = createTxWalletGrazConnector({
|
|
30
|
+
handlers: {
|
|
31
|
+
connect: async ({ chainId, appId, callbackUrl }) => {
|
|
32
|
+
// map into existing TX Wallet connect/request rails
|
|
33
|
+
return {
|
|
34
|
+
accountAddress: 'core1example...',
|
|
35
|
+
chainId,
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
signAdr36: async ({ appId, requestId, callbackUrl, challenge }) => {
|
|
39
|
+
// map into existing TX Wallet sign-in approval flow
|
|
40
|
+
return {
|
|
41
|
+
status: 'approved',
|
|
42
|
+
requestId,
|
|
43
|
+
signature: {
|
|
44
|
+
pubKey: 'A1B2...',
|
|
45
|
+
signature: 'MEQC...',
|
|
46
|
+
signed: challenge,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
disconnect: async () => {
|
|
51
|
+
// clear session state only
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await connector.connect({
|
|
57
|
+
chainId: 'coreum-mainnet-1',
|
|
58
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
59
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const account = await connector.getAccount();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Live TX Wallet Auth-backed usage
|
|
66
|
+
|
|
67
|
+
Use the built-in handlers when you want this connector to call your existing TX Wallet Auth endpoints directly.
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import {
|
|
71
|
+
createTxWalletGrazAuthConnector,
|
|
72
|
+
} from '@txwallet/graz-connector';
|
|
73
|
+
|
|
74
|
+
const connector = createTxWalletGrazAuthConnector({
|
|
75
|
+
requestOrigin: window.location.origin,
|
|
76
|
+
walletBaseUrl: 'https://txwallet.tesbert.com',
|
|
77
|
+
supportedChains: ['coreum-mainnet-1', 'coreum-testnet-1'],
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
await connector.connect({
|
|
81
|
+
chainId: 'coreum-mainnet-1',
|
|
82
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
83
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
84
|
+
statement: 'Connect with TX Wallet',
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
const signResult = await connector.signAdr36({
|
|
88
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
89
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
90
|
+
challenge: {
|
|
91
|
+
statement: 'Sign in with TX Wallet.',
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
console.log(signResult.status, signResult.requestId);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Notes:
|
|
99
|
+
|
|
100
|
+
- `connect()` creates and polls a standard sign-in request and returns normalized account context.
|
|
101
|
+
- `signAdr36()` uses the same approval rail and returns approved/rejected/failed terminal status.
|
|
102
|
+
- If your backend already created a sign-in request, pass `requestId` to `signAdr36()`.
|
|
103
|
+
- Unknown `chainId` values now fail fast with `UNSUPPORTED_CHAIN` before network calls. Override allowed chains with `supportedChains` when needed.
|
|
104
|
+
- Callback and status URL origins are enforced against `requestOrigin`; mismatches fail fast with `CALLBACK_ORIGIN_MISMATCH` before network calls.
|
|
105
|
+
- Fallback handoff URLs are enforced against the configured `walletBaseUrl` origin; mismatches fail fast with `CALLBACK_ORIGIN_MISMATCH` before opening a wallet window.
|
|
106
|
+
- Status payload `request_id` values are integrity-checked against the expected request id; mismatches fail with `REQUEST_FAILED` to prevent cross-request result confusion.
|
|
107
|
+
|
|
108
|
+
## React / Graz hook usage
|
|
109
|
+
|
|
110
|
+
Graz is hooks-first, so `@txwallet/graz-connector/react` ships a `useTxWalletGrazConnector` hook with graz-style ergonomics. Pass auth-handler options (a connector is built once on mount) or an existing connector instance. `react` is an optional peer dependency.
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { useTxWalletGrazConnector } from '@txwallet/graz-connector/react';
|
|
114
|
+
|
|
115
|
+
function ConnectTxWallet() {
|
|
116
|
+
const { connect, signAdr36, disconnect, account, error, isConnecting, isConnected } =
|
|
117
|
+
useTxWalletGrazConnector({
|
|
118
|
+
requestOrigin: window.location.origin,
|
|
119
|
+
walletBaseUrl: 'https://txwallet.tesbert.com',
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (isConnected) {
|
|
123
|
+
return (
|
|
124
|
+
<div>
|
|
125
|
+
<p>Connected: {account?.accountAddress}</p>
|
|
126
|
+
<button onClick={() => signAdr36({
|
|
127
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
128
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
129
|
+
challenge: { statement: 'Sign in with TX Wallet.' },
|
|
130
|
+
})}>Sign in</button>
|
|
131
|
+
<button onClick={() => disconnect()}>Disconnect</button>
|
|
132
|
+
</div>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return (
|
|
137
|
+
<button
|
|
138
|
+
disabled={isConnecting}
|
|
139
|
+
onClick={() => connect({
|
|
140
|
+
chainId: 'coreum-mainnet-1',
|
|
141
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
142
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
143
|
+
})}
|
|
144
|
+
>
|
|
145
|
+
{isConnecting ? 'Connecting…' : 'Connect TX Wallet'}{error ? ` — ${error.code}` : ''}
|
|
146
|
+
</button>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Hook actions are fire-and-forget safe (failures surface through `error`/`status`, no unhandled rejections); use the returned `connector` directly when you need the raw awaitable/throwing calls.
|
|
152
|
+
|
|
153
|
+
## Transaction Requests
|
|
154
|
+
|
|
155
|
+
Use the transaction-request handlers when Graz-oriented integrations need to launch a typed TX Wallet Request instead of an ADR-36 sign-in.
|
|
156
|
+
|
|
157
|
+
```js
|
|
158
|
+
import { createTxWalletGrazTransactionConnector } from '@txwallet/graz-connector';
|
|
159
|
+
|
|
160
|
+
const connector = createTxWalletGrazTransactionConnector({
|
|
161
|
+
requestOrigin: window.location.origin,
|
|
162
|
+
walletBaseUrl: 'https://txwallet.tesbert.com',
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const result = await connector.requestTransaction({
|
|
166
|
+
appId: 'txapp_01JZ8S3J9M3N7Q2K5R9V6X4H1A',
|
|
167
|
+
callbackUrl: 'https://partner.example.com/tx-wallet/callback',
|
|
168
|
+
chainId: 'coreum-mainnet-1',
|
|
169
|
+
body: {
|
|
170
|
+
category: 'token_payment',
|
|
171
|
+
payer: 'core1payer...',
|
|
172
|
+
recipient: 'core1recipient...',
|
|
173
|
+
amount: '1',
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
console.log(result.status, result.txHash);
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
For partners that already assemble the request envelope themselves, `requestTransaction()` also accepts prebuilt `requestId`, `statusUrl`, and `fallbackUrl` values.
|
|
181
|
+
|
|
182
|
+
Transaction support in this adapter is intentionally focused on the approved payment lanes. Keep checkout/payment mainnet lanes behind the existing app and rollout switches, and do not use the connector as a blind-signing surface.
|
|
183
|
+
- `requestTransaction()` launches and polls a typed TX Wallet Request and returns the final request status.
|
|
184
|
+
- The connector emits a request result through the same connector state machine, but the request rail is still separate from ADR-36 sign-in.
|
|
185
|
+
- Review-only categories are blocked by default in the transaction handlers to prevent accidental production onboarding mistakes; use `allowReviewOnly: true` only for explicit review-fixture workflows.
|
|
186
|
+
|
|
187
|
+
## Error behavior
|
|
188
|
+
|
|
189
|
+
Expected stable error code buckets include:
|
|
190
|
+
|
|
191
|
+
- `WALLET_LOCKED`
|
|
192
|
+
- `NO_ACTIVE_ACCOUNT`
|
|
193
|
+
- `UNSUPPORTED_CHAIN`
|
|
194
|
+
- `REQUEST_EXPIRED`
|
|
195
|
+
- `CALLBACK_ORIGIN_MISMATCH`
|
|
196
|
+
- `USER_REJECTED`
|
|
197
|
+
- `REQUEST_FAILED`
|
|
198
|
+
- `NETWORK_ERROR`
|
|
199
|
+
- `INTERNAL_ERROR`
|
|
200
|
+
|
|
201
|
+
## Boundary
|
|
202
|
+
|
|
203
|
+
Use this adapter as a compatibility bridge into existing TX Wallet Auth rails.
|
|
204
|
+
Treat TX Wallet protocol docs and server/client rails as authoritative behavior.
|
|
205
|
+
Do not bypass approval UI, policy checks, or request validation.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
export const TX_WALLET_GRAZ_CONNECTOR_VERSION: '0.1.0';
|
|
2
|
+
export const TX_WALLET_GRAZ_DEFAULT_SIGNIN_CREATE_ENDPOINT: '/api/tx-wallet/signin/requests';
|
|
3
|
+
export const TX_WALLET_GRAZ_DEFAULT_TRANSACTION_CREATE_ENDPOINT: '/api/tx-wallet/requests';
|
|
4
|
+
|
|
5
|
+
export interface TxWalletGrazConnectedAccount {
|
|
6
|
+
accountAddress: string;
|
|
7
|
+
chainId: string;
|
|
8
|
+
walletName: 'TX Wallet';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface TxWalletGrazAccount {
|
|
12
|
+
accountAddress: string;
|
|
13
|
+
chainId: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TxWalletGrazSignResult {
|
|
17
|
+
status: 'approved' | 'rejected' | 'failed';
|
|
18
|
+
requestId: string;
|
|
19
|
+
txWalletResultUrl?: string;
|
|
20
|
+
signature?: {
|
|
21
|
+
pubKey: string;
|
|
22
|
+
signature: string;
|
|
23
|
+
signed: Record<string, unknown>;
|
|
24
|
+
};
|
|
25
|
+
error?: {
|
|
26
|
+
code: string;
|
|
27
|
+
message: string;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface TxWalletGrazTransactionResult {
|
|
32
|
+
status: 'broadcasted' | 'confirmed' | 'rejected' | 'failed' | 'expired' | 'unsupported' | 'invalid' | 'error';
|
|
33
|
+
requestId: string;
|
|
34
|
+
txWalletResultUrl?: string;
|
|
35
|
+
receiptUrl?: string;
|
|
36
|
+
txHash?: string;
|
|
37
|
+
receipt?: Record<string, unknown>;
|
|
38
|
+
error?: unknown;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface TxWalletGrazHandlers {
|
|
42
|
+
connect?: (input: {
|
|
43
|
+
chainId: string;
|
|
44
|
+
appId: string;
|
|
45
|
+
callbackUrl: string;
|
|
46
|
+
statement?: string;
|
|
47
|
+
}) => Promise<TxWalletGrazConnectedAccount | { accountAddress: string; chainId: string }>;
|
|
48
|
+
signAdr36?: (input: {
|
|
49
|
+
appId: string;
|
|
50
|
+
requestId?: string;
|
|
51
|
+
callbackUrl: string;
|
|
52
|
+
challenge?: Record<string, unknown>;
|
|
53
|
+
}) => Promise<TxWalletGrazSignResult>;
|
|
54
|
+
requestTransaction?: (input: {
|
|
55
|
+
appId: string;
|
|
56
|
+
requestId?: string;
|
|
57
|
+
callbackUrl: string;
|
|
58
|
+
chainId?: string;
|
|
59
|
+
body?: Record<string, unknown>;
|
|
60
|
+
statusUrl?: string;
|
|
61
|
+
fallbackUrl?: string;
|
|
62
|
+
}) => Promise<TxWalletGrazTransactionResult>;
|
|
63
|
+
disconnect?: () => Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface TxWalletGrazAuthHandlerOptions {
|
|
67
|
+
fetchImpl?: typeof fetch;
|
|
68
|
+
requestOrigin?: string;
|
|
69
|
+
createEndpoint?: string;
|
|
70
|
+
walletBaseUrl?: string;
|
|
71
|
+
credentials?: RequestCredentials;
|
|
72
|
+
pollIntervalMs?: number;
|
|
73
|
+
pollTimeoutMs?: number;
|
|
74
|
+
openWallet?: (fallbackUrl: string) => unknown;
|
|
75
|
+
supportedChains?: string[];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface TxWalletGrazConnectorOptions {
|
|
79
|
+
handlers?: TxWalletGrazHandlers;
|
|
80
|
+
initialChainId?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class TxWalletGrazConnectorError extends Error {
|
|
84
|
+
code: string;
|
|
85
|
+
details?: unknown;
|
|
86
|
+
cause?: unknown;
|
|
87
|
+
constructor(message: string, options?: { code?: string; details?: unknown; cause?: unknown });
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export class TxWalletGrazConnector {
|
|
91
|
+
state: 'idle' | 'connecting' | 'connected' | 'signing' | 'requesting' | 'error' | 'disconnected';
|
|
92
|
+
chainId: string;
|
|
93
|
+
accountAddress: string;
|
|
94
|
+
constructor(options?: TxWalletGrazConnectorOptions);
|
|
95
|
+
on(eventName: string, listener: (detail: unknown) => void): () => void;
|
|
96
|
+
off(eventName: string, listener: (detail: unknown) => void): void;
|
|
97
|
+
emit(eventName: string, detail: unknown): void;
|
|
98
|
+
setState(nextState: TxWalletGrazConnector['state']): void;
|
|
99
|
+
getState(): TxWalletGrazConnector['state'];
|
|
100
|
+
getSupportedSignStatuses(): Array<'approved' | 'rejected' | 'failed'>;
|
|
101
|
+
connect(input: { chainId: string; appId: string; callbackUrl: string; statement?: string }): Promise<TxWalletGrazConnectedAccount>;
|
|
102
|
+
getAccount(): Promise<TxWalletGrazAccount>;
|
|
103
|
+
signAdr36(input: {
|
|
104
|
+
appId: string;
|
|
105
|
+
requestId?: string;
|
|
106
|
+
callbackUrl: string;
|
|
107
|
+
challenge?: Record<string, unknown>;
|
|
108
|
+
}): Promise<TxWalletGrazSignResult>;
|
|
109
|
+
disconnect(): Promise<void>;
|
|
110
|
+
getSupportedRequestStatuses(): Array<'broadcasted' | 'confirmed' | 'rejected' | 'failed' | 'expired' | 'unsupported' | 'invalid' | 'error'>;
|
|
111
|
+
requestTransaction(input: {
|
|
112
|
+
appId: string;
|
|
113
|
+
requestId?: string;
|
|
114
|
+
callbackUrl: string;
|
|
115
|
+
chainId?: string;
|
|
116
|
+
body?: Record<string, unknown>;
|
|
117
|
+
statusUrl?: string;
|
|
118
|
+
fallbackUrl?: string;
|
|
119
|
+
}): Promise<TxWalletGrazTransactionResult>;
|
|
120
|
+
launchRequest(input: {
|
|
121
|
+
appId: string;
|
|
122
|
+
requestId?: string;
|
|
123
|
+
callbackUrl: string;
|
|
124
|
+
chainId?: string;
|
|
125
|
+
body?: Record<string, unknown>;
|
|
126
|
+
statusUrl?: string;
|
|
127
|
+
fallbackUrl?: string;
|
|
128
|
+
}): Promise<TxWalletGrazTransactionResult>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function createTxWalletGrazConnector(options?: TxWalletGrazConnectorOptions): TxWalletGrazConnector;
|
|
132
|
+
export function createTxWalletGrazAuthHandlers(options?: TxWalletGrazAuthHandlerOptions): TxWalletGrazHandlers;
|
|
133
|
+
export function createTxWalletGrazAuthConnector(
|
|
134
|
+
options?: TxWalletGrazAuthHandlerOptions & { initialChainId?: string }
|
|
135
|
+
): TxWalletGrazConnector;
|
|
136
|
+
export function createTxWalletGrazTransactionHandlers(options?: TxWalletGrazTransactionHandlerOptions): TxWalletGrazHandlers;
|
|
137
|
+
export function createTxWalletGrazTransactionConnector(
|
|
138
|
+
options?: TxWalletGrazTransactionHandlerOptions & { initialChainId?: string }
|
|
139
|
+
): TxWalletGrazConnector;
|
|
140
|
+
|
|
141
|
+
export interface TxWalletGrazTransactionHandlerOptions {
|
|
142
|
+
fetchImpl?: typeof fetch;
|
|
143
|
+
requestOrigin?: string;
|
|
144
|
+
createEndpoint?: string;
|
|
145
|
+
walletBaseUrl?: string;
|
|
146
|
+
credentials?: RequestCredentials;
|
|
147
|
+
pollIntervalMs?: number;
|
|
148
|
+
pollTimeoutMs?: number;
|
|
149
|
+
openWallet?: (fallbackUrl: string) => unknown;
|
|
150
|
+
allowReviewOnly?: boolean;
|
|
151
|
+
supportedChains?: string[];
|
|
152
|
+
}
|