odin-connect 1.2.1 → 1.3.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/.github/workflows/pr.yml +24 -24
- package/demo/README.md +69 -69
- package/demo/eslint.config.js +23 -23
- package/demo/index.html +13 -13
- package/demo/package-lock.json +3495 -3495
- package/demo/package.json +32 -32
- package/demo/public/icon.svg +5 -5
- package/demo/tsconfig.app.json +27 -27
- package/demo/tsconfig.node.json +25 -25
- package/demo/vite.config.ts +7 -7
- package/dist/services/canister.d.ts +7 -0
- package/dist/services/canister.d.ts.map +1 -1
- package/dist/services/canister.js +17 -0
- package/dist/services/connected-user.d.ts +2 -1
- package/dist/services/connected-user.d.ts.map +1 -1
- package/dist/services/connected-user.js +6 -0
- package/package.json +51 -51
- package/readme.md +468 -205
- package/vitest.config.ts +7 -7
- package/dist/services/connect.test.d.ts +0 -2
- package/dist/services/connect.test.d.ts.map +0 -1
- package/dist/services/connect.test.js +0 -323
package/readme.md
CHANGED
|
@@ -1,205 +1,468 @@
|
|
|
1
|
-
# OdinConnect
|
|
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
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
//
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
"
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
1
|
+
# OdinConnect
|
|
2
|
+
|
|
3
|
+
A TypeScript SDK for integrating with the [Odin](https://odin.fun) decentralized token platform on the Internet Computer (ICP). OdinConnect handles user authentication, token trading, liquidity management, and API interactions through a simple, promise-based interface.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Installation](#installation)
|
|
8
|
+
- [Architecture](#architecture)
|
|
9
|
+
- [How It Works](#how-it-works)
|
|
10
|
+
- [Authentication Flow](#authentication-flow)
|
|
11
|
+
- [Trading Action Flow](#trading-action-flow)
|
|
12
|
+
- [API Request Flow](#api-request-flow)
|
|
13
|
+
- [Getting Started](#getting-started)
|
|
14
|
+
- [Authentication](#authentication)
|
|
15
|
+
- [Connected User Operations](#connected-user-operations)
|
|
16
|
+
- [Fetching User Data](#fetching-user-data)
|
|
17
|
+
- [Trading](#trading)
|
|
18
|
+
- [Liquidity](#liquidity)
|
|
19
|
+
- [Token Creation](#token-creation)
|
|
20
|
+
- [Public API](#public-api)
|
|
21
|
+
- [Tokens](#tokens)
|
|
22
|
+
- [Users](#users)
|
|
23
|
+
- [Utilities](#utilities)
|
|
24
|
+
- [Configuration](#configuration)
|
|
25
|
+
- [Types](#types)
|
|
26
|
+
- [Demo](#demo)
|
|
27
|
+
- [General Notes](#general-notes)
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm i odin-connect
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Architecture
|
|
36
|
+
|
|
37
|
+
OdinConnect is built with a layered architecture. Your application interacts with the `OdinConnect` class, which delegates to specialized internal services:
|
|
38
|
+
|
|
39
|
+
```mermaid
|
|
40
|
+
graph TB
|
|
41
|
+
App["Your Application"]
|
|
42
|
+
|
|
43
|
+
subgraph OdinConnect SDK
|
|
44
|
+
OC["OdinConnect<br/>(Entry Point)"]
|
|
45
|
+
CU["ConnectedUser<br/>(Authenticated Session)"]
|
|
46
|
+
API["OdinApiClient<br/>(REST API)"]
|
|
47
|
+
CAN["OdinCanisterClient<br/>(Blockchain Actions)"]
|
|
48
|
+
WIN["WindowClient<br/>(Popup Management)"]
|
|
49
|
+
HTTP["HttpClient<br/>(Axios + BigInt)"]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
OdinAPI["Odin API Server"]
|
|
53
|
+
OdinFE["Odin Frontend<br/>(Popup Window)"]
|
|
54
|
+
|
|
55
|
+
App --> OC
|
|
56
|
+
OC --> CU
|
|
57
|
+
OC --> API
|
|
58
|
+
CU --> API
|
|
59
|
+
CU --> CAN
|
|
60
|
+
CAN --> WIN
|
|
61
|
+
WIN --> OdinFE
|
|
62
|
+
API --> HTTP
|
|
63
|
+
HTTP --> OdinAPI
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Component | Role |
|
|
67
|
+
|-----------|------|
|
|
68
|
+
| **OdinConnect** | Main entry point. Initializes the SDK with your app info and environment. |
|
|
69
|
+
| **ConnectedUser** | Returned after authentication. Provides user-scoped data fetching and trading actions. |
|
|
70
|
+
| **OdinApiClient** | Handles all REST API calls to `api.odin.fun`. Available both on the instance (`odinConnect.api`) and on the connected user. |
|
|
71
|
+
| **OdinCanisterClient** | Manages popup-based authorization for blockchain actions (buy, sell, transfer, etc.). |
|
|
72
|
+
| **WindowClient** | Wraps `window.open()` for cross-origin popup communication via `postMessage`. |
|
|
73
|
+
| **HttpClient** | Axios wrapper with automatic BigInt deserialization for large number fields. |
|
|
74
|
+
|
|
75
|
+
## How It Works
|
|
76
|
+
|
|
77
|
+
### Authentication Flow
|
|
78
|
+
|
|
79
|
+
When your app calls `connect()`, a popup opens to the Odin frontend where the user signs in. On success, user credentials are passed back to your app via `postMessage`.
|
|
80
|
+
|
|
81
|
+
```mermaid
|
|
82
|
+
sequenceDiagram
|
|
83
|
+
participant App as Your App
|
|
84
|
+
participant SDK as OdinConnect SDK
|
|
85
|
+
participant Popup as Odin Frontend (Popup)
|
|
86
|
+
participant User as User
|
|
87
|
+
|
|
88
|
+
App->>SDK: odinConnect.connect(options)
|
|
89
|
+
SDK->>Popup: window.open(odin.fun/authorize/connect?...)
|
|
90
|
+
Popup->>User: Show sign-in UI
|
|
91
|
+
User->>Popup: Authenticates
|
|
92
|
+
Popup->>SDK: postMessage({ principal, jwt, delegationChain? })
|
|
93
|
+
SDK->>SDK: Create ConnectedUser instance
|
|
94
|
+
SDK->>App: Returns ConnectedUser
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**What gets returned depends on your options:**
|
|
98
|
+
|
|
99
|
+
| Option | What You Get |
|
|
100
|
+
|--------|-------------|
|
|
101
|
+
| `requires_api: true` | A JWT token for authenticated API calls (image uploads, etc.) |
|
|
102
|
+
| `requires_delegation: true` | A `DelegationIdentity` for direct canister calls |
|
|
103
|
+
| Neither | Basic connection with user's principal |
|
|
104
|
+
|
|
105
|
+
### Trading Action Flow
|
|
106
|
+
|
|
107
|
+
Trading operations (buy, sell, transfer, swap, liquidity) each open a popup for the user to authorize the transaction:
|
|
108
|
+
|
|
109
|
+
```mermaid
|
|
110
|
+
sequenceDiagram
|
|
111
|
+
participant App as Your App
|
|
112
|
+
participant SDK as ConnectedUser
|
|
113
|
+
participant Popup as Odin Frontend (Popup)
|
|
114
|
+
participant User as User
|
|
115
|
+
participant Chain as ICP Blockchain
|
|
116
|
+
|
|
117
|
+
App->>SDK: user.buy({ token, btcAmount })
|
|
118
|
+
SDK->>Popup: window.open(odin.fun/authorize/buy?...)
|
|
119
|
+
Popup->>User: Show transaction details
|
|
120
|
+
User->>Popup: Approves transaction
|
|
121
|
+
Popup->>Chain: Execute on-chain transaction
|
|
122
|
+
Chain->>Popup: Transaction result
|
|
123
|
+
Popup->>SDK: postMessage("purchased")
|
|
124
|
+
SDK->>App: Returns true
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
If the user rejects the transaction, the popup sends `"rejected"` and the promise resolves to `false`.
|
|
128
|
+
|
|
129
|
+
### API Request Flow
|
|
130
|
+
|
|
131
|
+
API calls go through the HttpClient, which automatically handles BigInt deserialization for fields like `marketcap`, `volume`, and `balance`:
|
|
132
|
+
|
|
133
|
+
```mermaid
|
|
134
|
+
flowchart LR
|
|
135
|
+
A["Your App"] --> B["OdinApiClient"]
|
|
136
|
+
B --> C["HttpClient<br/>(Axios + BigInt parser)"]
|
|
137
|
+
C --> D["api.odin.fun/v1"]
|
|
138
|
+
D --> C
|
|
139
|
+
C --> B
|
|
140
|
+
B --> A
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Getting Started
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { OdinConnect } from "odin-connect";
|
|
147
|
+
|
|
148
|
+
// 1. Initialize
|
|
149
|
+
const odinConnect = new OdinConnect({
|
|
150
|
+
name: "My App",
|
|
151
|
+
env: "prod",
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
// 2. Authenticate a user
|
|
155
|
+
const user = await odinConnect.connect({
|
|
156
|
+
requires_api: true,
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// 3. Fetch data
|
|
160
|
+
const balances = await user.getBalances({ page: 1, limit: 10 });
|
|
161
|
+
|
|
162
|
+
// 4. Perform actions
|
|
163
|
+
await user.buy({ token: "2jjj", btcAmount: 10_000_000n });
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Authentication
|
|
167
|
+
|
|
168
|
+
### Initializing a new instance
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
const odinConnect = new OdinConnect({
|
|
172
|
+
name: "Demo App", // Your app name (shown in auth popup)
|
|
173
|
+
env: "prod", // "prod" | "dev" | "local"
|
|
174
|
+
});
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Connecting a user
|
|
178
|
+
|
|
179
|
+
```typescript
|
|
180
|
+
const user = await odinConnect.connect({
|
|
181
|
+
// window.open() settings for the auth popup
|
|
182
|
+
open: {
|
|
183
|
+
target: "_blank",
|
|
184
|
+
settings: "height=800,width=400",
|
|
185
|
+
},
|
|
186
|
+
// Request a JWT for authenticated API calls
|
|
187
|
+
requires_api: true,
|
|
188
|
+
// Request a DelegationChain for direct canister interaction
|
|
189
|
+
requires_delegation: false,
|
|
190
|
+
});
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Getting a Delegation Identity
|
|
194
|
+
|
|
195
|
+
If you need to make direct calls to ICP canisters, request a delegation:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const user = await odinConnect.connect({
|
|
199
|
+
requires_delegation: true,
|
|
200
|
+
targets: ["aaaa-aa"], // Canister IDs the delegation is scoped to
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
const identity = user.getIdentity();
|
|
204
|
+
// Use identity with @dfinity/agent
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Connected User Operations
|
|
208
|
+
|
|
209
|
+
After calling `connect()`, you receive a `ConnectedUser` with the following capabilities:
|
|
210
|
+
|
|
211
|
+
### Fetching User Data
|
|
212
|
+
|
|
213
|
+
All data methods accept a `{ page, limit }` pagination object:
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const profile = await user.getUser();
|
|
217
|
+
const balances = await user.getBalances({ page: 1, limit: 10 });
|
|
218
|
+
const tokens = await user.getTokens({ page: 1, limit: 10 });
|
|
219
|
+
const createdTokens = await user.getCreatedTokens({ page: 1, limit: 10 });
|
|
220
|
+
const liquidity = await user.getLiquidity({ page: 1, limit: 10 });
|
|
221
|
+
const activity = await user.getActivity({ page: 1, limit: 10 });
|
|
222
|
+
const achievements = await user.getAchievements({ page: 1, limit: 10 });
|
|
223
|
+
const transactions = await user.getTransactions({ page: 1, limit: 10 });
|
|
224
|
+
const stats = await user.getStats();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Trading
|
|
228
|
+
|
|
229
|
+
#### Buy tokens
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
await user.buy({
|
|
233
|
+
btcAmount: 10_000_000n, // Amount in millisatoshis
|
|
234
|
+
token: "2jjj",
|
|
235
|
+
});
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### Sell tokens
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
await user.sell({
|
|
242
|
+
tokenAmount: 20_000_000n,
|
|
243
|
+
token: "2jjj",
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
#### Transfer tokens
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
await odinConnect.transfer({
|
|
251
|
+
principal: "veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe",
|
|
252
|
+
destination: "vv5jb-7sm7u-vn3nq-6nflf-dghis-fd7ji-cx764-xunni-zosog-eqvpw-oae",
|
|
253
|
+
token: "2jjj",
|
|
254
|
+
amount: 20_000_000n,
|
|
255
|
+
});
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### Swap tokens
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
await user.swap({
|
|
262
|
+
fromToken: "2jjj",
|
|
263
|
+
toToken: "abc1",
|
|
264
|
+
fromAmount: 10_000_000n,
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Liquidity
|
|
269
|
+
|
|
270
|
+
#### Add liquidity
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
await user.addLiquidity({
|
|
274
|
+
btcAmount: 20_000_000n,
|
|
275
|
+
token: "2jj",
|
|
276
|
+
});
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
#### Remove liquidity
|
|
280
|
+
|
|
281
|
+
```typescript
|
|
282
|
+
await user.removeLiquidity({
|
|
283
|
+
btcAmount: 20_000_000n,
|
|
284
|
+
token: "2jj",
|
|
285
|
+
});
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Token Creation
|
|
289
|
+
|
|
290
|
+
> **Note:** `requires_api` must be set to `true` when connecting.
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
const user = await odinConnect.connect({ requires_api: true });
|
|
294
|
+
|
|
295
|
+
await user.createToken({
|
|
296
|
+
image: file, // A File (PNG, JPEG, WebP, GIF, SVG, or AVIF; max 200KB)
|
|
297
|
+
principal: "veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe",
|
|
298
|
+
name: "Test Token", // 3-30 characters
|
|
299
|
+
ticker: "TEST", // 3-10 uppercase alphanumeric, at least 2 letters
|
|
300
|
+
description: "A test token", // Optional, max 100 characters
|
|
301
|
+
website: "https://example.com", // Optional, valid URL
|
|
302
|
+
telegram: "", // Optional, valid Telegram URL
|
|
303
|
+
twitter: "", // Optional, valid Twitter/X URL
|
|
304
|
+
buy: 20_000_000n, // Optional, pre-buy amount in millisats
|
|
305
|
+
discount: "", // Optional, 10 alphanumeric characters
|
|
306
|
+
});
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Public API
|
|
310
|
+
|
|
311
|
+
The API client is available at `odinConnect.api` and does **not** require authentication for read operations.
|
|
312
|
+
|
|
313
|
+
### Tokens
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
// List tokens with sorting and filtering
|
|
317
|
+
const tokens = await odinConnect.api.getTokens(
|
|
318
|
+
{ page: 1, limit: 10 }, // Pagination
|
|
319
|
+
{ field: "marketcap", direction: "desc" }, // Sort (optional)
|
|
320
|
+
{ marketcap_min: 100_000_000n } // Filters (optional)
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
// Get a single token by ID
|
|
324
|
+
const token = await odinConnect.api.getToken("2jjj");
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Available sort fields:** `marketcap`, `volume`, `price`, `holder_count`, `created_time`
|
|
328
|
+
|
|
329
|
+
**Available filters:**
|
|
330
|
+
|
|
331
|
+
| Filter | Type | Description |
|
|
332
|
+
|--------|------|-------------|
|
|
333
|
+
| `ascended` | `boolean` | Token has ascended |
|
|
334
|
+
| `etched` | `boolean` | Token has been etched |
|
|
335
|
+
| `external` | `boolean` | External (Bitcoin) token |
|
|
336
|
+
| `verified` | `boolean` | Verified token |
|
|
337
|
+
| `has_website` | `boolean` | Has a website |
|
|
338
|
+
| `has_twitter` | `boolean` | Has a Twitter account |
|
|
339
|
+
| `has_telegram` | `boolean` | Has a Telegram group |
|
|
340
|
+
| `marketcap_min` / `marketcap_max` | `bigint` | Market cap range (millisats) |
|
|
341
|
+
| `volume_min` / `volume_max` | `bigint` | Volume range (millisats) |
|
|
342
|
+
| `holders_min` / `holders_max` | `number` | Holder count range |
|
|
343
|
+
| `price_min` / `price_max` | `number` | Price range |
|
|
344
|
+
| `search` | `string` | Search by name or ticker |
|
|
345
|
+
|
|
346
|
+
### Users
|
|
347
|
+
|
|
348
|
+
```typescript
|
|
349
|
+
// Get activities (no principal required)
|
|
350
|
+
const activity = await odinConnect.api.getUserActivity({
|
|
351
|
+
pagination: { page: 1, limit: 10 },
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
// Get token by id
|
|
355
|
+
const token = await odinConnect.api.getToken("2jjj");
|
|
356
|
+
|
|
357
|
+
// Get user profile by id
|
|
358
|
+
const user = await odinConnect.api.getUser(
|
|
359
|
+
"veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe"
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
// Get user balances by user id
|
|
363
|
+
const balances = await odinConnect.api.getBalances(
|
|
364
|
+
"veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe",
|
|
365
|
+
{ page: 1, limit: 20 }
|
|
366
|
+
);
|
|
367
|
+
|
|
368
|
+
// Get activities by user id
|
|
369
|
+
const activity = await odinConnect.api.getUserActivity(
|
|
370
|
+
"veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe",
|
|
371
|
+
{ page: 1, limit: 10 }
|
|
372
|
+
);
|
|
373
|
+
|
|
374
|
+
// Get transactions by user id
|
|
375
|
+
const transactions = await odinConnect.api.getUserTransactions(
|
|
376
|
+
"veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe",
|
|
377
|
+
{ page: 1, limit: 10 }
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
// Get user stats
|
|
381
|
+
const stats = await odinConnect.api.getUserStats(
|
|
382
|
+
"veyov-kjgrf-hke6v-6d63i-sdwae-oldgg-huau6-ke5g3-rllp2-5jhca-uqe"
|
|
383
|
+
);
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Utilities
|
|
387
|
+
|
|
388
|
+
OdinConnect exports utility functions under `OdinUtils`:
|
|
389
|
+
|
|
390
|
+
```typescript
|
|
391
|
+
import { OdinUtils } from "odin-connect";
|
|
392
|
+
|
|
393
|
+
// Convert a decimal amount to the on-chain bigint representation
|
|
394
|
+
const amount = OdinUtils.convertToOdinAmount("1.5", token);
|
|
395
|
+
// For a token with decimals=3, divisibility=8 → 150_000_000_000n
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Token Field Validators
|
|
399
|
+
|
|
400
|
+
Validators are available for token creation fields:
|
|
401
|
+
|
|
402
|
+
```typescript
|
|
403
|
+
import { OdinUtils } from "odin-connect";
|
|
404
|
+
|
|
405
|
+
OdinUtils.createTokenValidators.name("My Token"); // 3-30 chars
|
|
406
|
+
OdinUtils.createTokenValidators.ticker("TEST"); // 3-10 uppercase alphanumeric
|
|
407
|
+
OdinUtils.createTokenValidators.image(file); // PNG/JPEG/WebP/GIF/SVG/AVIF, max 200KB
|
|
408
|
+
OdinUtils.createTokenValidators.description("A token"); // Max 100 chars
|
|
409
|
+
OdinUtils.createTokenValidators.website("https://..."); // Valid URL
|
|
410
|
+
OdinUtils.createTokenValidators.twitter("https://x.com/...");
|
|
411
|
+
OdinUtils.createTokenValidators.telegram("https://t.me/...");
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Configuration
|
|
415
|
+
|
|
416
|
+
### Environments
|
|
417
|
+
|
|
418
|
+
| Environment | Frontend URL | API Base URL |
|
|
419
|
+
|-------------|-------------|-------------|
|
|
420
|
+
| `prod` (default) | `https://odin.fun` | `https://api.odin.fun/v1` |
|
|
421
|
+
| `dev` | `https://dev.odin.fun` | `https://api.odin.fun/dev` |
|
|
422
|
+
| `local` | `http://localhost:5173` | `https://api.odin.fun/dev` |
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
const odinConnect = new OdinConnect({
|
|
426
|
+
name: "My App",
|
|
427
|
+
env: "dev", // Use development environment
|
|
428
|
+
});
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
## Types
|
|
432
|
+
|
|
433
|
+
All types are exported with the `Odin` prefix:
|
|
434
|
+
|
|
435
|
+
```typescript
|
|
436
|
+
import type {
|
|
437
|
+
OdinUser,
|
|
438
|
+
OdinBalance,
|
|
439
|
+
OdinBaseToken,
|
|
440
|
+
OdinToken,
|
|
441
|
+
OdinTokenWithBalance,
|
|
442
|
+
OdinActivity,
|
|
443
|
+
OdinTransaction,
|
|
444
|
+
OdinAchievement,
|
|
445
|
+
OdinAchievementCategory,
|
|
446
|
+
OdinConnectedUser,
|
|
447
|
+
} from "odin-connect";
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
## Demo
|
|
451
|
+
|
|
452
|
+
This repository includes a working demo application in the `/demo` folder.
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
# Build the library and start the demo dev server
|
|
456
|
+
npm run demo
|
|
457
|
+
|
|
458
|
+
# Or run just the demo (if already built)
|
|
459
|
+
npm run demo:start
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
## General Notes
|
|
463
|
+
|
|
464
|
+
- All BTC amounts are in **millisatoshis** (1 BTC = 100,000,000,000 millisats)
|
|
465
|
+
- All trading actions (buy, sell, transfer, swap, liquidity) open a popup for user authorization and return a `boolean`
|
|
466
|
+
- API data methods return paginated results; pass `{ page, limit }` to control pagination
|
|
467
|
+
- The SDK uses `postMessage` for secure cross-origin communication between your app and the Odin frontend popup
|
|
468
|
+
- BigInt fields (balances, amounts, market caps) are automatically deserialized from JSON
|