kredo 0.1.0 → 0.2.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.
- package/README.md +11 -7
- package/dist/client.d.ts +13 -8
- package/dist/client.js +13 -9
- package/dist/network.d.ts +2 -3
- package/dist/network.js +1 -1
- package/dist/types.d.ts +13 -3
- package/package.json +10 -5
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# kredo
|
|
2
2
|
|
|
3
|
-
Charge Kredo credits from your server. Your users buy credits once and spend them in every app on the network. You're paid in USDT on
|
|
3
|
+
Charge Kredo credits from your server. Your users buy credits once and spend them in every app on the network. You're paid in USDT on NEAR for what they spend with you.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```bash
|
|
6
|
+
npm install kredo
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
No dependencies. Node 18+. It talks to the live network on NEAR testnet by default: pass `baseUrl` and `pagesUrl` to point it elsewhere.
|
|
6
10
|
|
|
7
11
|
## Quick start
|
|
8
12
|
|
|
@@ -38,7 +42,7 @@ Every app also gets a test key, `uc_test_...`, from the dashboard. Use it in pla
|
|
|
38
42
|
|
|
39
43
|
```ts
|
|
40
44
|
const credits = new Credits({ apiKey: process.env.CREDITS_TEST_KEY! });
|
|
41
|
-
const { user } = await credits.exchangeCode(`cc_test_${
|
|
45
|
+
const { user } = await credits.exchangeCode(`cc_test_${someAccount}`); // any account, no hosted page
|
|
42
46
|
await credits.charge({ user, credits: 10 });
|
|
43
47
|
```
|
|
44
48
|
|
|
@@ -50,14 +54,14 @@ A user has to approve a spending limit for your app before you can charge them.
|
|
|
50
54
|
|
|
51
55
|
1. Send them to the connect page: `await credits.connectUrl({ credits: 200, returnTo })`.
|
|
52
56
|
2. They sign in with email, approve the limit, and come back to `returnTo?code=...`.
|
|
53
|
-
3. On your server, swap the code for their
|
|
57
|
+
3. On your server, swap the code for their NEAR account and keep it in your session:
|
|
54
58
|
|
|
55
59
|
```ts
|
|
56
60
|
const { user } = await credits.exchangeCode(req.query.code);
|
|
57
61
|
req.session.creditsUser = user;
|
|
58
62
|
```
|
|
59
63
|
|
|
60
|
-
Never take a user's
|
|
64
|
+
Never take a user's NEAR account from the browser. The code works once, only for your app, for 10 minutes.
|
|
61
65
|
|
|
62
66
|
The React kit ([`kredo-react`](../react)) does this in a popup, and `credits.session(user)` returns exactly what the kit renders.
|
|
63
67
|
|
|
@@ -66,14 +70,14 @@ The React kit ([`kredo-react`](../react)) does this in a popup, and `credits.ses
|
|
|
66
70
|
| Call | What it does |
|
|
67
71
|
|---|---|
|
|
68
72
|
| `quote({ action, quantity })` | Price in credits and dollars, and what you keep after the network fee |
|
|
69
|
-
| `user(
|
|
73
|
+
| `user(account)` | Balance, whether they connected you, the limit left, and what's spendable now |
|
|
70
74
|
| `charge({ user, action \| credits, ref })` | Charges now |
|
|
71
75
|
| `hold({ user, action \| credits, ref, ttlSeconds })` | Reserves credits for a job, price locked |
|
|
72
76
|
| `capture(holdId, { credits? })` | Charges all or part of a hold, returns the rest |
|
|
73
77
|
| `release(holdId)` | Returns the whole hold |
|
|
74
78
|
| `refund({ user, credits, ref })` | Gives credits back, up to what they spent with you |
|
|
75
79
|
| `setExchangeRate(rate)`, `convert({ user, credits })` | Light mode: sell your own credits for ours |
|
|
76
|
-
| `payout()` | Pays your unpaid earnings in USDT to your payout
|
|
80
|
+
| `payout()` | Pays your unpaid earnings in USDT to your payout account |
|
|
77
81
|
| `activity()`, `exportCsv()`, `gas()` | Reporting. Gas is paid by the network, never by you or your users |
|
|
78
82
|
| `setWebhook(url)`, `webhookDeliveries()` | Signed event delivery |
|
|
79
83
|
| `connectUrl()`, `buyUrl()`, `accountUrl()` | Links to the hosted pages |
|
package/dist/client.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type { ActivityItem, Amount, CreditsSession, AmountInput, AppInfo, Capture, Conversion, Credits as CreditAmount, GasReport, Hold, HoldStatus, Operation, Payout, PriceList, PriceListInput, Quote, UserState, WebhookDelivery } from "./types.js";
|
|
1
|
+
import type { ActivityItem, Amount, CreditsSession, AmountInput, AppInfo, AppProfileInput, Capture, Conversion, Credits as CreditAmount, GasReport, Hold, HoldStatus, Operation, Payout, PriceList, PriceListInput, Quote, UserState, WebhookDelivery } from "./types.js";
|
|
2
2
|
export type CreditsOptions = {
|
|
3
3
|
/** Your app's API key, `uc_live_...`. */
|
|
4
4
|
apiKey: string;
|
|
5
|
-
/** The network's API. Defaults to https://kredo-api.onrender.com. */
|
|
5
|
+
/** The network's API. Defaults to https://kredo-near-api.onrender.com. */
|
|
6
6
|
baseUrl?: string;
|
|
7
|
-
/** The network's hosted pages (connect, buy, wallet). Defaults to https://kredo-
|
|
7
|
+
/** The network's hosted pages (connect, buy, wallet). Defaults to https://kredo-near.vercel.app. */
|
|
8
8
|
pagesUrl?: string;
|
|
9
9
|
/** Extra tries after a network failure or a rate limit. Writes are safe to retry: each carries a ref. Default 2. */
|
|
10
10
|
retries?: number;
|
|
@@ -23,15 +23,20 @@ export declare class Credits {
|
|
|
23
23
|
private readonly timeoutMs;
|
|
24
24
|
private readonly fetchFn;
|
|
25
25
|
constructor(opts: CreditsOptions);
|
|
26
|
-
/** Your app: payout
|
|
26
|
+
/** Your app: payout account, fee, unpaid earnings, prices and webhook. */
|
|
27
27
|
app(): Promise<AppInfo>;
|
|
28
28
|
prices(): Promise<PriceList>;
|
|
29
29
|
/** Replaces your price list, in credits: `{ "chat.message": { price: 2 }, "video.render": { rate: 8, unit: "second" } }`. */
|
|
30
30
|
setPrices(prices: PriceListInput): Promise<PriceList>;
|
|
31
|
+
/** Sets how your app appears in the Kredo directory: name, description, logo, website and category. */
|
|
32
|
+
setProfile(profile: AppProfileInput): Promise<AppProfileInput & {
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
}>;
|
|
31
36
|
/** What an action costs the user, and what you keep after the network fee. Show it before the job starts. */
|
|
32
37
|
quote(input: AmountInput): Promise<Quote>;
|
|
33
38
|
/** A user's balance, whether they've connected your app, and the most you can charge them now. */
|
|
34
|
-
user(
|
|
39
|
+
user(account: string): Promise<UserState>;
|
|
35
40
|
/**
|
|
36
41
|
* Charges the user now. Pass your own `ref` (an order or message id) to make retries safe:
|
|
37
42
|
* the same ref always returns the first result. Throws a CreditsError with `isDeclined` when
|
|
@@ -89,8 +94,8 @@ export declare class Credits {
|
|
|
89
94
|
/** @deprecated Use accountUrl(). */
|
|
90
95
|
walletUrl(): string;
|
|
91
96
|
/**
|
|
92
|
-
* Swaps the one-time code from the connect page for the user's
|
|
93
|
-
* your server, then keep both in your own session. Never take an
|
|
97
|
+
* Swaps the one-time code from the connect page for the user's NEAR account and email. Call it from
|
|
98
|
+
* your server, then keep both in your own session. Never take an account from the browser.
|
|
94
99
|
*/
|
|
95
100
|
exchangeCode(code: string): Promise<{
|
|
96
101
|
user: string;
|
|
@@ -105,7 +110,7 @@ export declare class Credits {
|
|
|
105
110
|
session(user: string | undefined, opts?: {
|
|
106
111
|
email?: string | null;
|
|
107
112
|
}): Promise<CreditsSession>;
|
|
108
|
-
/** Pays all your unpaid earnings in USDT to your payout
|
|
113
|
+
/** Pays all your unpaid earnings in USDT to your payout account, on NEAR. */
|
|
109
114
|
payout(): Promise<Payout>;
|
|
110
115
|
/** Every vault event for your app, newest first. */
|
|
111
116
|
activity(opts?: {
|
package/dist/client.js
CHANGED
|
@@ -26,14 +26,14 @@ export class Credits {
|
|
|
26
26
|
if (!opts.apiKey)
|
|
27
27
|
throw new Error("Credits: apiKey is required");
|
|
28
28
|
this.apiKey = opts.apiKey;
|
|
29
|
-
this.baseUrl = (opts.baseUrl ?? "https://kredo-api.onrender.com").replace(/\/+$/, "");
|
|
30
|
-
this.pagesUrl = (opts.pagesUrl ?? "https://kredo-
|
|
29
|
+
this.baseUrl = (opts.baseUrl ?? "https://kredo-near-api.onrender.com").replace(/\/+$/, "");
|
|
30
|
+
this.pagesUrl = (opts.pagesUrl ?? "https://kredo-near.vercel.app").replace(/\/+$/, "");
|
|
31
31
|
this.retries = opts.retries ?? 2;
|
|
32
32
|
this.timeoutMs = opts.timeoutMs ?? 60_000;
|
|
33
33
|
this.fetchFn = opts.fetch ?? globalThis.fetch;
|
|
34
34
|
}
|
|
35
35
|
// ---------------------------------------------------------------- your app
|
|
36
|
-
/** Your app: payout
|
|
36
|
+
/** Your app: payout account, fee, unpaid earnings, prices and webhook. */
|
|
37
37
|
async app() {
|
|
38
38
|
const app = await this.request("GET", "/v1/app");
|
|
39
39
|
this.appId = app.id;
|
|
@@ -46,14 +46,18 @@ export class Credits {
|
|
|
46
46
|
setPrices(prices) {
|
|
47
47
|
return this.request("PUT", "/v1/prices", { body: { prices } });
|
|
48
48
|
}
|
|
49
|
+
/** Sets how your app appears in the Kredo directory: name, description, logo, website and category. */
|
|
50
|
+
setProfile(profile) {
|
|
51
|
+
return this.request("PATCH", "/v1/profile", { body: profile });
|
|
52
|
+
}
|
|
49
53
|
// ---------------------------------------------------------------- prices and users
|
|
50
54
|
/** What an action costs the user, and what you keep after the network fee. Show it before the job starts. */
|
|
51
55
|
quote(input) {
|
|
52
56
|
return this.request("GET", "/v1/quote", { query: amountQuery(input) });
|
|
53
57
|
}
|
|
54
58
|
/** A user's balance, whether they've connected your app, and the most you can charge them now. */
|
|
55
|
-
user(
|
|
56
|
-
return this.request("GET", `/v1/users/${encodeURIComponent(
|
|
59
|
+
user(account) {
|
|
60
|
+
return this.request("GET", `/v1/users/${encodeURIComponent(account)}`);
|
|
57
61
|
}
|
|
58
62
|
// ---------------------------------------------------------------- charging
|
|
59
63
|
/**
|
|
@@ -114,8 +118,8 @@ export class Credits {
|
|
|
114
118
|
return this.accountUrl();
|
|
115
119
|
}
|
|
116
120
|
/**
|
|
117
|
-
* Swaps the one-time code from the connect page for the user's
|
|
118
|
-
* your server, then keep both in your own session. Never take an
|
|
121
|
+
* Swaps the one-time code from the connect page for the user's NEAR account and email. Call it from
|
|
122
|
+
* your server, then keep both in your own session. Never take an account from the browser.
|
|
119
123
|
*/
|
|
120
124
|
exchangeCode(code) {
|
|
121
125
|
return this.request("POST", "/v1/connect/exchange", { body: { code } });
|
|
@@ -132,11 +136,11 @@ export class Credits {
|
|
|
132
136
|
const u = await this.user(user);
|
|
133
137
|
return {
|
|
134
138
|
app,
|
|
135
|
-
user: {
|
|
139
|
+
user: { account: u.user, email: opts.email ?? null, balance: u.balance, connected: u.connected, limit: u.limit, spendable: u.spendable },
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
142
|
// ---------------------------------------------------------------- money out and reporting
|
|
139
|
-
/** Pays all your unpaid earnings in USDT to your payout
|
|
143
|
+
/** Pays all your unpaid earnings in USDT to your payout account, on NEAR. */
|
|
140
144
|
payout() {
|
|
141
145
|
return this.request("POST", "/v1/payout", { body: {} });
|
|
142
146
|
}
|
package/dist/network.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { Amount, DirectoryEntry, NetworkStats, Reserves } from "./types.js";
|
|
2
2
|
export type Health = {
|
|
3
3
|
ok: boolean;
|
|
4
|
-
|
|
4
|
+
network: string;
|
|
5
5
|
block: number;
|
|
6
6
|
vault: string;
|
|
7
7
|
usdt: string;
|
|
8
8
|
relayer: {
|
|
9
|
-
|
|
9
|
+
account: string;
|
|
10
10
|
balance: string;
|
|
11
11
|
symbol: string;
|
|
12
12
|
};
|
|
@@ -14,7 +14,6 @@ export type Health = {
|
|
|
14
14
|
indexer: {
|
|
15
15
|
block: number;
|
|
16
16
|
head: number;
|
|
17
|
-
lag: number;
|
|
18
17
|
backed: boolean;
|
|
19
18
|
events: number;
|
|
20
19
|
pendingWebhooks: number;
|
package/dist/network.js
CHANGED
|
@@ -4,7 +4,7 @@ export class CreditsNetwork {
|
|
|
4
4
|
baseUrl;
|
|
5
5
|
fetchFn;
|
|
6
6
|
constructor(opts = {}) {
|
|
7
|
-
this.baseUrl = (opts.baseUrl ?? "https://kredo-api.onrender.com").replace(/\/+$/, "");
|
|
7
|
+
this.baseUrl = (opts.baseUrl ?? "https://kredo-near-api.onrender.com").replace(/\/+$/, "");
|
|
8
8
|
this.fetchFn = opts.fetch ?? globalThis.fetch;
|
|
9
9
|
}
|
|
10
10
|
health() {
|
package/dist/types.d.ts
CHANGED
|
@@ -80,6 +80,15 @@ export type PriceListInput = Record<string, {
|
|
|
80
80
|
rate: Credits;
|
|
81
81
|
unit: string;
|
|
82
82
|
}>;
|
|
83
|
+
export type AppCategory = "ai" | "media" | "audio" | "developer" | "games" | "productivity" | "other";
|
|
84
|
+
/** How your app appears in the Kredo directory. Fields left out stay as they are. */
|
|
85
|
+
export type AppProfileInput = {
|
|
86
|
+
name?: string;
|
|
87
|
+
description?: string;
|
|
88
|
+
logoUrl?: string;
|
|
89
|
+
website?: string;
|
|
90
|
+
category?: AppCategory;
|
|
91
|
+
};
|
|
83
92
|
export type AppInfo = {
|
|
84
93
|
id: string;
|
|
85
94
|
name: string;
|
|
@@ -102,11 +111,12 @@ export type Payout = Operation & {
|
|
|
102
111
|
to: string;
|
|
103
112
|
usdt: string;
|
|
104
113
|
};
|
|
114
|
+
/** Gas the network paid for your app's transactions: yoctoNEAR, and the same as NEAR in `gas`. */
|
|
105
115
|
export type GasReport = {
|
|
106
116
|
transactions: number;
|
|
107
|
-
|
|
117
|
+
yocto: string;
|
|
108
118
|
gas: string;
|
|
109
|
-
symbol:
|
|
119
|
+
symbol: "NEAR";
|
|
110
120
|
paidBy: "network";
|
|
111
121
|
};
|
|
112
122
|
/** One vault event, newest first in every feed. */
|
|
@@ -177,7 +187,7 @@ export type CreditsSession = {
|
|
|
177
187
|
name: string;
|
|
178
188
|
};
|
|
179
189
|
user: {
|
|
180
|
-
|
|
190
|
+
account: string;
|
|
181
191
|
email: string | null;
|
|
182
192
|
balance: Amount;
|
|
183
193
|
connected: boolean;
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kredo",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Server kit for charging Kredo credits from a company backend",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"homepage": "https://kredo-
|
|
6
|
+
"homepage": "https://kredo-near.vercel.app/docs/sdk",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/chandrabosep/near-hacks-kredo.git",
|
|
10
|
+
"directory": "packages/sdk"
|
|
11
|
+
},
|
|
7
12
|
"keywords": [
|
|
8
13
|
"kredo",
|
|
9
14
|
"credits",
|
|
10
15
|
"payments",
|
|
11
16
|
"usdt",
|
|
12
|
-
"
|
|
17
|
+
"near",
|
|
13
18
|
"sdk"
|
|
14
19
|
],
|
|
15
20
|
"type": "module",
|
|
@@ -35,9 +40,9 @@
|
|
|
35
40
|
},
|
|
36
41
|
"devDependencies": {
|
|
37
42
|
"@types/node": "^20.19.43",
|
|
43
|
+
"near-api-js": "7.4.0",
|
|
38
44
|
"tsx": "^4.23.15",
|
|
39
|
-
"typescript": "^5.9.3"
|
|
40
|
-
"viem": "^2.57.16"
|
|
45
|
+
"typescript": "^5.9.3"
|
|
41
46
|
},
|
|
42
47
|
"publishConfig": {
|
|
43
48
|
"access": "public"
|