gondi 0.43.0 → 0.44.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 +116 -17
- package/dist/index.mjs +68 -52
- package/dist/index.mjs.map +4 -4
- package/dist/src/blockchain.d.ts +2 -0
- package/dist/src/clients/api/index.d.ts +4 -0
- package/dist/src/clients/api/sdk.d.ts +4 -0
- package/dist/src/clients/contracts/MslV6.d.ts +7 -0
- package/dist/src/errors.d.ts +14 -0
- package/dist/src/generated/graphql/index.d.ts +21 -0
- package/dist/src/gondi.d.ts +16 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -1
package/README.md
CHANGED
|
@@ -6,6 +6,10 @@ A JavaScript library for crypto-native lending: borrow, lend & refinance NFTs (n
|
|
|
6
6
|
|
|
7
7
|
- [Installation](#installation)
|
|
8
8
|
- [Getting Started](#getting-started)
|
|
9
|
+
- [Headless lender (scripts and AI agents)](#headless-lender-scripts-and-ai-agents)
|
|
10
|
+
- [Supported chains and currencies](#supported-chains-and-currencies)
|
|
11
|
+
- [Reading lending data](#reading-lending-data)
|
|
12
|
+
- [Risks](#risks)
|
|
9
13
|
- [Examples](#examples)
|
|
10
14
|
- [Need help migrating between versions? Check our Changelog!](./CHANGELOG.md)
|
|
11
15
|
|
|
@@ -42,6 +46,103 @@ const gondi = new Gondi({ wallet });
|
|
|
42
46
|
|
|
43
47
|
Typescript types are included in the package.
|
|
44
48
|
|
|
49
|
+
## Headless lender (scripts and AI agents)
|
|
50
|
+
|
|
51
|
+
A lender needs no browser: a private key is enough. The first API call signs a Sign-In with
|
|
52
|
+
Ethereum message with the wallet (a signature, no gas) and the SDK reuses the session afterwards.
|
|
53
|
+
Publishing, listing and hiding offers are API calls; approving the currency and cancelling an
|
|
54
|
+
offer are onchain transactions.
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
import { Gondi, OfferStatus } from 'gondi';
|
|
58
|
+
import { createWalletClient, http, parseEther } from 'viem';
|
|
59
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
60
|
+
import { mainnet } from 'viem/chains';
|
|
61
|
+
|
|
62
|
+
const WETH = '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2';
|
|
63
|
+
const SECONDS_PER_DAY = 86_400n;
|
|
64
|
+
|
|
65
|
+
const wallet = createWalletClient({
|
|
66
|
+
account: privateKeyToAccount(process.env.PRIVATE_KEY),
|
|
67
|
+
transport: http(process.env.RPC_URL),
|
|
68
|
+
chain: mainnet,
|
|
69
|
+
});
|
|
70
|
+
const gondi = new Gondi({ wallet });
|
|
71
|
+
|
|
72
|
+
// 1. Let the loan contract pull the principal when a borrower takes the offer (onchain, once).
|
|
73
|
+
const principalAmount = parseEther('1');
|
|
74
|
+
if (!(await gondi.isApprovedToken({ tokenAddress: WETH, amount: principalAmount }))) {
|
|
75
|
+
const approval = await gondi.approveToken({ tokenAddress: WETH }); // Unlimited unless you pass `amount`.
|
|
76
|
+
await approval.waitTxInBlock();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// 2. Find the collection to lend against (`gondi.collections({})` pages through all of them).
|
|
80
|
+
const collectionId = await gondi.collectionId({ slug: 'pudgypenguins' });
|
|
81
|
+
|
|
82
|
+
// 3. Sign and publish a collection offer.
|
|
83
|
+
const offer = await gondi.makeCollectionOffer({
|
|
84
|
+
collectionId,
|
|
85
|
+
principalAddress: WETH,
|
|
86
|
+
principalAmount,
|
|
87
|
+
capacity: principalAmount, // Total you lend across every loan taken from this offer.
|
|
88
|
+
fee: 0n, // Origination fee, in principal units.
|
|
89
|
+
aprBps: 1_000n, // 10% APR.
|
|
90
|
+
duration: 30n * SECONDS_PER_DAY, // In seconds; see "Loan durations" below.
|
|
91
|
+
expirationTime: BigInt(Math.floor(Date.now() / 1_000)) + SECONDS_PER_DAY, // Valid for one day.
|
|
92
|
+
maxSeniorRepayment: 0n, // 0n: the offer only funds a loan's first (senior) tranche.
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// 4. List your active offers (pass `cursor` back to read the next page while `hasNextPage`).
|
|
96
|
+
const { offers, cursor, hasNextPage } = await gondi.offers({
|
|
97
|
+
filterBy: { lenders: [wallet.account.address], status: [OfferStatus.Active] },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// 5. Withdraw it. `hideOffer` only removes it from the API (no gas): the signed offer stays
|
|
101
|
+
// executable onchain until it expires. `cancelOffer` invalidates it onchain.
|
|
102
|
+
await gondi.hideOffer({ id: offer.offerId, contractAddress: offer.contractAddress });
|
|
103
|
+
const cancellation = await gondi.cancelOffer({
|
|
104
|
+
id: offer.offerId,
|
|
105
|
+
contractAddress: offer.contractAddress,
|
|
106
|
+
});
|
|
107
|
+
await cancellation.waitTxInBlock();
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
[`examples/headlessLender.ts`](./examples/headlessLender.ts) runs the same flow against the
|
|
111
|
+
local chain the other examples use (see [`examples/common.ts`](./examples/common.ts) for the
|
|
112
|
+
environment it reads).
|
|
113
|
+
|
|
114
|
+
API errors are thrown as an `Error` whose message is the JSON of the GraphQL errors.
|
|
115
|
+
|
|
116
|
+
### Loan durations
|
|
117
|
+
|
|
118
|
+
`duration` is in seconds and must be a whole number of days: a multiple of 30 days, or one of the
|
|
119
|
+
short terms the API accepts (currently 3, 5, 7, 10, 15, 20 or 45 days). Other values fail with
|
|
120
|
+
`INVALID_OFFER_DURATION_ERROR`.
|
|
121
|
+
|
|
122
|
+
## Supported chains and currencies
|
|
123
|
+
|
|
124
|
+
The SDK picks the contracts from the wallet's chain. Amounts are in the currency's smallest unit.
|
|
125
|
+
|
|
126
|
+
| Chain | viem chain | Chain id | Principal currencies |
|
|
127
|
+
| ---------------- | ----------- | -------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
128
|
+
| Ethereum mainnet | `mainnet` | 1 | WETH `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`, USDC (6 decimals) `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48` |
|
|
129
|
+
| HyperEVM | `hyperEvm` | 999 | WHYPE `0x5555555555555555555555555555555555555555`, USDC (6 decimals) `0xb88339CB7199b77E23DB6E890353E22632Ba630f` |
|
|
130
|
+
| Robinhood Chain | `robinhood` | 4663 | WETH `0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73`, USDG (6 decimals) `0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168` |
|
|
131
|
+
|
|
132
|
+
## Reading lending data
|
|
133
|
+
|
|
134
|
+
Lending data is public: the GraphQL API at https://api.gondi.xyz/graphql answers reads without
|
|
135
|
+
authentication and supports introspection, so any GraphQL client can explore the schema and query
|
|
136
|
+
collections, offers and loans directly.
|
|
137
|
+
|
|
138
|
+
## Risks
|
|
139
|
+
|
|
140
|
+
The collateral is an NFT. If the borrower does not repay by the end of the term, the lender does
|
|
141
|
+
not get the principal back: a loan with a single lender is foreclosed and the lender claims the
|
|
142
|
+
NFT (`liquidateLoan`), whose value may be below what was lent; a loan split across several
|
|
143
|
+
tranches goes to auction instead. The protocol takes a fee on the interest the lender earns (and
|
|
144
|
+
on any origination fee); `getProtocolFee` reads it.
|
|
145
|
+
|
|
45
146
|
## Examples
|
|
46
147
|
|
|
47
148
|
### Getting NFT/Collection ids
|
|
@@ -63,19 +164,18 @@ const collectionId = (
|
|
|
63
164
|
#### Single NFT Offer
|
|
64
165
|
|
|
65
166
|
```javascript
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
borrowerAddress, // Optional: allow only this borrower to accept the offer.
|
|
167
|
+
const offer = await gondi.makeSingleNftOffer({
|
|
168
|
+
nftId: 1,
|
|
169
|
+
principalAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // Principal currency address (e.g. WETH).
|
|
170
|
+
principalAmount: 1_000_000_000_000_000_000n, // In the currency's smallest unit (e.g. 1 WETH in wei).
|
|
171
|
+
capacity: 1_000_000_000_000_000_000n, // How much you lend in total; for N loans on a collection offer, N * principalAmount.
|
|
172
|
+
fee: 0n, // Origination fee.
|
|
173
|
+
aprBps: 100n, // APR in basis points (e.g. 1% APR).
|
|
174
|
+
expirationTime: BigInt(Math.floor(Date.now() / 1_000) + 86_400), // Seconds since epoch (e.g. one day from now).
|
|
175
|
+
duration: 2_592_000n, // Seconds (e.g. 30 days); see "Loan durations".
|
|
176
|
+
maxSeniorRepayment: 0n, // 0n: the offer only funds a loan's first (senior) tranche.
|
|
177
|
+
requiresLiquidation, // Sets the collateral to be liquidated on default.
|
|
178
|
+
borrowerAddress, // Optional: allow only this borrower to accept the offer.
|
|
79
179
|
});
|
|
80
180
|
```
|
|
81
181
|
|
|
@@ -107,7 +207,7 @@ available where the API has trait loan offers enabled.
|
|
|
107
207
|
```javascript
|
|
108
208
|
import { OffersSortField, Ordering } from 'gondi';
|
|
109
209
|
const offer = await gondi.offers({
|
|
110
|
-
|
|
210
|
+
cursor, // Cursor returned by previous calls.
|
|
111
211
|
limit, // Number results.
|
|
112
212
|
sortBy: {
|
|
113
213
|
// Sort criteria.
|
|
@@ -122,9 +222,8 @@ const offer = await gondi.offers({
|
|
|
122
222
|
|
|
123
223
|
```javascript
|
|
124
224
|
const listings = await gondi.listings({
|
|
125
|
-
|
|
225
|
+
cursor, // Cursor returned by previous calls.
|
|
126
226
|
limit, // Number results.
|
|
127
|
-
|
|
128
|
-
filterBy, // Filter criteria, result is conjunction of components.
|
|
227
|
+
collections, // Optional: only listings of these collection ids.
|
|
129
228
|
});
|
|
130
229
|
```
|