forked from solana-labs/solana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SPL token lending scaffolding (solana-labs#582)
* Scaffolding for spl-token-lending program * Scaffolding for TS client
- Loading branch information
Showing
32 changed files
with
3,391 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Lending program | ||
|
||
A lending protocol for the Token program on the Solana blockchain inspired by Aave. | ||
|
||
Full documentation will be made available at https://spl.solana.com in the future | ||
|
||
Web3 bindings are available in the `./js` directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
{ | ||
"root": true, | ||
"env": { | ||
"node": true, | ||
"browser": true | ||
}, | ||
"extends": [ | ||
"eslint:recommended", | ||
"plugin:@typescript-eslint/eslint-recommended", | ||
"plugin:@typescript-eslint/recommended", | ||
"plugin:@typescript-eslint/recommended-requiring-type-checking", | ||
"prettier", | ||
"prettier/@typescript-eslint" | ||
], | ||
"parser": "@typescript-eslint/parser", | ||
"parserOptions": { | ||
"ecmaVersion": 2020, | ||
"parser": "babel-eslint", | ||
"project": "./tsconfig.json", | ||
"sourceType": "module" | ||
}, | ||
"plugins": [ | ||
"@typescript-eslint", | ||
"prettier" | ||
], | ||
"rules": { | ||
"no-console": 0, | ||
"semi": 0, | ||
"template-curly-spacing": [ | ||
2, | ||
"always" | ||
], | ||
"@typescript-eslint/no-explicit-any": 0 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
node_modules | ||
coverage | ||
.nyc_output | ||
.DS_Store | ||
*.log | ||
.vscode | ||
.idea | ||
dist | ||
compiled | ||
.awcache | ||
.rpt2_cache | ||
docs | ||
lib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
# Token-lending JavaScript API | ||
|
||
The Token-lending JavaScript library comprises: | ||
|
||
* A library to interact with the on-chain program | ||
* A test client that exercises the program | ||
* Scripts to facilitate building the program | ||
|
||
## Getting Started | ||
|
||
First fetch the npm dependencies, including `@solana/web3.js`, by running: | ||
```sh | ||
$ npm install | ||
``` | ||
|
||
### Select a Network | ||
|
||
The client connects to a local Solana cluster by default. | ||
|
||
To enable on-chain program logs, set the `RUST_LOG` environment variable: | ||
|
||
```bash | ||
$ export RUST_LOG=solana_runtime::native_loader=trace,solana_runtime::system_instruction_processor=trace,solana_runtime::bank=debug,solana_bpf_loader=debug,solana_rbpf=debug | ||
``` | ||
|
||
To start a local Solana cluster run: | ||
```bash | ||
$ npm run localnet:update | ||
$ npm run localnet:up | ||
``` | ||
|
||
Solana cluster logs are available with: | ||
```bash | ||
$ npm run localnet:logs | ||
``` | ||
|
||
For more details on working with a local cluster, see the [full | ||
instructions](https://github.com/solana-labs/solana-web3.js#local-network). | ||
|
||
### Build the on-chain program | ||
|
||
```bash | ||
$ npm run build:program | ||
``` | ||
|
||
### Run the test client | ||
|
||
```sh | ||
$ npm run start | ||
``` | ||
|
||
## Pointing to a public Solana cluster | ||
|
||
Solana maintains three public clusters: | ||
- `devnet` - Development cluster | ||
- `testnet` - Tour De Sol test cluster | ||
- `mainnet-beta` - Main cluster | ||
|
||
Use npm scripts to configure which cluster. | ||
|
||
To point to `devnet`: | ||
```bash | ||
$ npm run cluster:devnet | ||
``` | ||
|
||
To point back to the local cluster: | ||
```bash | ||
$ npm run cluster:localnet | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Exercises the token-lending program | ||
*/ | ||
|
||
import { loadPrograms } from "./token-lending-test"; | ||
|
||
async function main() { | ||
// These test cases are designed to run sequentially and in the following order | ||
console.log("Run test: loadPrograms"); | ||
await loadPrograms(); | ||
console.log("Success\n"); | ||
} | ||
|
||
main().then( | ||
() => process.exit(), | ||
(err) => { | ||
console.error(err); | ||
process.exit(-1); | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import fs from "mz/fs"; | ||
import { | ||
Account, | ||
Connection, | ||
BpfLoader, | ||
PublicKey, | ||
BPF_LOADER_PROGRAM_ID, | ||
} from "@solana/web3.js"; | ||
|
||
import { Store } from "../client/util/store"; | ||
import { newAccountWithLamports } from "../client/util/new-account-with-lamports"; | ||
import { url } from "../client/util/url"; | ||
|
||
let connection: Connection | undefined; | ||
async function getConnection(): Promise<Connection> { | ||
if (connection) return connection; | ||
|
||
connection = new Connection(url, "recent"); | ||
const version = await connection.getVersion(); | ||
|
||
console.log("Connection to cluster established:", url, version); | ||
return connection; | ||
} | ||
|
||
export async function loadPrograms(): Promise<void> { | ||
const connection = await getConnection(); | ||
const [tokenProgramId, tokenSwapProgramId] = await GetPrograms(connection); | ||
|
||
console.log("Token Program ID", tokenProgramId.toString()); | ||
console.log("Token-swap Program ID", tokenSwapProgramId.toString()); | ||
} | ||
|
||
async function loadProgram( | ||
connection: Connection, | ||
path: string | ||
): Promise<PublicKey> { | ||
const data = await fs.readFile(path); | ||
const { feeCalculator } = await connection.getRecentBlockhash(); | ||
|
||
const loaderCost = | ||
feeCalculator.lamportsPerSignature * | ||
BpfLoader.getMinNumSignatures(data.length); | ||
const minAccountBalance = await connection.getMinimumBalanceForRentExemption( | ||
0 | ||
); | ||
const minExecutableBalance = await connection.getMinimumBalanceForRentExemption( | ||
data.length | ||
); | ||
const balanceNeeded = minAccountBalance + loaderCost + minExecutableBalance; | ||
|
||
const from = await newAccountWithLamports(connection, balanceNeeded); | ||
const program_account = new Account(); | ||
console.log("Loading program:", path); | ||
await BpfLoader.load( | ||
connection, | ||
from, | ||
program_account, | ||
data, | ||
BPF_LOADER_PROGRAM_ID | ||
); | ||
return program_account.publicKey; | ||
} | ||
|
||
async function GetPrograms( | ||
connection: Connection | ||
): Promise<[PublicKey, PublicKey]> { | ||
const store = new Store(); | ||
let tokenProgramId = null; | ||
let tokenLendingProgramId = null; | ||
try { | ||
const config = await store.load("config.json"); | ||
console.log("Using pre-loaded Token and Token-lending programs"); | ||
console.log( | ||
" Note: To reload programs remove client/util/store/config.json" | ||
); | ||
if ("tokenProgramId" in config && "tokenLendingProgramId" in config) { | ||
tokenProgramId = new PublicKey(config["tokenProgramId"]); | ||
tokenLendingProgramId = new PublicKey(config["tokenLendingProgramId"]); | ||
} else { | ||
throw new Error("Program ids not found"); | ||
} | ||
} catch (err) { | ||
tokenProgramId = await loadProgram( | ||
connection, | ||
"../../target/bpfel-unknown-unknown/release/spl_token.so" | ||
); | ||
tokenLendingProgramId = await loadProgram( | ||
connection, | ||
"../../target/bpfel-unknown-unknown/release/spl_token_lending.so" | ||
); | ||
await store.save("config.json", { | ||
tokenProgramId: tokenProgramId.toString(), | ||
tokenSwapProgramId: tokenLendingProgramId.toString(), | ||
}); | ||
} | ||
return [tokenProgramId, tokenLendingProgramId]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { Connection } from "@solana/web3.js"; | ||
|
||
export class TokenLending { | ||
connection: Connection; | ||
|
||
constructor(connection: Connection) { | ||
this.connection = connection; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Account, Connection } from "@solana/web3.js"; | ||
|
||
export async function newAccountWithLamports( | ||
connection: Connection, | ||
lamports = 1000000 | ||
): Promise<Account> { | ||
const account = new Account(); | ||
const signature = await connection.requestAirdrop( | ||
account.publicKey, | ||
lamports | ||
); | ||
await connection.confirmTransaction(signature); | ||
return account; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// zzz | ||
export function sleep(ms: number): Promise<void> { | ||
return new Promise((resolve) => setTimeout(resolve, ms)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/** | ||
* Simple file-based datastore | ||
*/ | ||
|
||
import path from "path"; | ||
import fs from "mz/fs"; | ||
import mkdirp from "mkdirp"; | ||
|
||
type Config = { [key: string]: string }; | ||
|
||
export class Store { | ||
static getDir(): string { | ||
return path.join(__dirname, "store"); | ||
} | ||
|
||
async load(uri: string): Promise<Config> { | ||
const filename = path.join(Store.getDir(), uri); | ||
const data = await fs.readFile(filename, "utf8"); | ||
return JSON.parse(data) as Config; | ||
} | ||
|
||
async save(uri: string, config: Config): Promise<void> { | ||
await mkdirp(Store.getDir()); | ||
const filename = path.join(Store.getDir(), uri); | ||
await fs.writeFile(filename, JSON.stringify(config), "utf8"); | ||
} | ||
} |
Oops, something went wrong.