Skip to content

Commit

Permalink
Project import generated by Copybara.
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 7a1c4c2aea4e5abb9a59bbdf4df8ac959c643d7e
  • Loading branch information
Copybara authored and actions-user committed Nov 26, 2024
1 parent 3b0600a commit ed2cadf
Show file tree
Hide file tree
Showing 172 changed files with 57,742 additions and 0 deletions.
3 changes: 3 additions & 0 deletions javascript/on-demand/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
index.cjs
index.js
index.d.ts
40 changes: 40 additions & 0 deletions javascript/on-demand/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<div align="center">

![Switchboard Logo](https://github.com/switchboard-xyz/switchboard/raw/main/website/static/img/icons/switchboard/avatar.png)

# Switchboard

</div>

# Switchboard On-Demand (typedoc: https://switchboard-docs.web.app)
See the full documentation at [Switchboard On-Demand Documentation](https://switchboard-labs.gitbook.io/switchboard-on-demand/)

Switchboard On-Demand is designed to support high-fidelity financial systems. It allows users to specify how data from both on-chain and off-chain sources is ingested and transformed.

Unlike many pull-based blockchain oracles that manage data consensus on their own Layer 1 (L1) and then propagate it to users—giving oracle operators an advantage—Switchboard Oracles operate inside confidential runtimes. This setup ensures that oracles cannot observe the data they are collecting or the operations they perform, giving the end user a 'first-look' advantage when data is propagated.

Switchboard On-Demand is ideal for blockchain-based financial applications and services, offering a solution that is cost-effective, trustless, and user-friendly.

## Key Features:
- **User-Created Oracles**: In Switchboard, users have the flexibility to build their own oracles according to their specific needs.
- **Confidential Runtimes**: Oracle operations are performed in a way that even the oracles themselves cannot observe, ensuring data integrity and user advantage.
- **High-Fidelity Financial Applications**: Designed with financial applications in mind, Switchboard ensures high accuracy and reliability for transactions and data handling.

## Getting Started
To start building your own on-demand oracle with Switchboard, you can refer to the oracle specification in our [documentation](https://protos.docs.switchboard.xyz/protos/OracleJob).

### Example Code Snippet:
```typescript
const [pullIx] = await feedAccount.fetchUpdateIx({ numSignatures: 3 });
const tx = await sb.asV0Tx({
connection,
ixs: [pullIx],
signers: [payer],
computeUnitPrice: 200_000,
computeUnitLimitMultiple: 1.3,
});
await program.provider.connection.sendTransaction(tx, {
// preflightCommitment is REQUIRED to be processed or disabled
preflightCommitment: "processed",
});
```
9 changes: 9 additions & 0 deletions javascript/on-demand/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"hosting": [
{
"site": "switchboard-docs",
"public": "docs",
"rewrites": [{ "source": "**", "destination": "/index.html" }]
}
]
}
40 changes: 40 additions & 0 deletions javascript/on-demand/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@switchboard-xyz/on-demand",
"version": "1.2.51",
"description": "A Typescript client to interact with Switchboard On-Demand.",
"license": "ISC",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/types/esm/index.d.ts",
"files": [
"dist"
],
"scripts": {
"build": "tsc && tsc --project tsconfig.cjs.json",
"check-types": "tsc --noEmit",
"docgen": "typedoc --out ./docs/ ./src",
"docgen:deploy": "pnpm docgen && firebase deploy --project docs --only hosting:switchboard-docs",
"prepack": "pnpm build",
"test": "pnpm exec jest --passWithNoTests"
},
"dependencies": {
"@brokerloop/ttlcache": "^3.2.3",
"@coral-xyz/anchor-30": "npm:@coral-xyz/[email protected]",
"@solana/web3.js": "^1.95.0",
"@solworks/soltoolkit-sdk": "^0.0.23",
"@switchboard-xyz/common": "^",
"axios": "^1.7.4",
"big.js": "^6.2.1",
"bs58": "^5.0.0",
"js-yaml": "^4.1.0",
"protobufjs": "^7.2.6"
},
"devDependencies": {
"jest": "^29.7.0",
"typedoc": "^0.25.9",
"typescript": "5.4.5"
},
"engines": {
"node": ">= 18"
}
}
7 changes: 7 additions & 0 deletions javascript/on-demand/src/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export * from "./lutMap.js";
export * from "./oracle.js";
export * from "./permission.js";
export * from "./pullFeed.js";
export * from "./queue.js";
export * from "./randomness.js";
export * from "./state.js";
166 changes: 166 additions & 0 deletions javascript/on-demand/src/accounts/lutMap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { RecentSlotHashes } from "./../sysvars/recentSlothashes.js";
import * as spl from "./../utils/index.js";
import { Queue } from "./queue.js";
import { State } from "./state.js";

import type { BN, Program } from "@coral-xyz/anchor-30";
import type {
AddressLookupTableState,
TransactionInstruction,
} from "@solana/web3.js";
import {
AddressLookupTableAccount,
AddressLookupTableProgram,
PublicKey,
SystemProgram,
} from "@solana/web3.js";

/**
* A map of LUTs to their public keys.
*
* Users can initialize to compact all oracle and feed keys they use into a single
* account, and then use the LUT to load all tx keys efficiently.
*/
export class LutMap {
/**
* The public key of the LUT map account.
*/
static async keyFromSeed(
program: Program,
queue: PublicKey,
authority: PublicKey
): Promise<PublicKey> {
const [lut] = PublicKey.findProgramAddressSync(
[
Buffer.from("LutMapAccountData"),
queue.toBuffer(),
authority.toBuffer(),
],
program.programId
);
return lut;
}

/**
* Creating a LUT map account will allow a user or protocol to easy manage
* and associate a common account grouping for their feeds to reduce the
* total number of transaction bytes taken by Switchboard.
* This will maximize the flexibility users have in their instructions.
*
* @param program - The program that owns the LUT map account.
* @param queue - The queue account that the LUT map is associated with.
* @param slot - The slot that the LUT map is associated with.
* @returns A promise that resolves to the LUT map and the transaction signature.
*/
static async create(
program: Program,
queue: PublicKey,
slot: BN
): Promise<[LutMap, string]> {
const payer = (program.provider as any).wallet.payer;
const lutKey = await LutMap.keyFromSeed(program, queue, payer.publicKey);
const sig = await program.rpc.lutMapInit(
{ slot },
{
accounts: {
lutMap: lutKey,
queue: queue,
payer: payer.publicKey,
authority: payer.publicKey,
systemProgram: SystemProgram.programId,
},
signers: [payer],
}
);
return [new LutMap(program, lutKey), sig];
}

constructor(readonly program: Program, readonly pubkey: PublicKey) {}

async queueLutExtendIx(params: {
queue: PublicKey;
newKey: PublicKey;
payer: PublicKey;
}): Promise<TransactionInstruction> {
const payer = (this.program.provider as any).wallet.payer;
const queueAccount = new Queue(this.program, params.queue);
const queueData = await queueAccount.loadData();
const lutKey = await LutMap.keyFromSeed(
this.program,
params.queue,
payer.publicKey
);
const lutSigner = (
await PublicKey.findProgramAddress(
[Buffer.from("LutSigner"), params.queue.toBuffer()],
this.program.programId
)
)[0];
const ix = await this.program.instruction.queueLutExtend(
{ newKey: params.newKey },
{
accounts: {
queue: params.queue,
authority: queueData.authority,
lutSigner,
lut: lutKey,
addressLookupTableProgram: AddressLookupTableProgram.programId,
payer: payer.publicKey,
systemProgram: SystemProgram.programId,
},
}
);
return ix;
}

/**
* Loads the data for this {@linkcode LutMap} account from on chain.
*
* @returns A promise that resolves to the data.
* @throws if the account does not exist.
*/
async loadData(): Promise<any> {
return await this.program.account["lutMapAccountData"].fetch(this.pubkey);
}

async loadLut(): Promise<[PublicKey, AddressLookupTableState]> {
const data = await this.loadData();
const lutKey = data.lut;
const lutAccountInfo =
await this.program.provider.connection.getAccountInfo(lutKey);
const lutData = AddressLookupTableAccount.deserialize(lutAccountInfo!.data);
return [lutKey, lutData];
}

async syncLut(feeds: PublicKey[]): Promise<void> {
const wrapperData = await this.loadData();
const [key, data] = await this.loadLut();
const queueKey = wrapperData.queue;
const queue = new Queue(this.program, queueKey);
const queueData = await queue.loadData();
const oracles = queueData.oracleKeys.slice(0, queueData.oracleKeysLen);
const neededLutAccounts: PublicKey[] = [];
neededLutAccounts.push(queueKey);
neededLutAccounts.push(spl.NATIVE_MINT);
neededLutAccounts.push(spl.TOKEN_PROGRAM_ID);
neededLutAccounts.push(spl.ASSOCIATED_TOKEN_PROGRAM_ID);
neededLutAccounts.push(State.keyFromSeed(this.program));
for (const oracle of oracles) {
for (const feed of feeds) {
const [statsKey] = PublicKey.findProgramAddressSync(
[Buffer.from("OracleFeedStats"), feed.toBuffer(), oracle.toBuffer()],
this.program.programId
);
const feedRewardEscrow = await spl.getAssociatedTokenAddress(
spl.NATIVE_MINT,
feed
);
neededLutAccounts.push(statsKey);
neededLutAccounts.push(feed);
neededLutAccounts.push(oracle);
neededLutAccounts.push(feedRewardEscrow);
}
}
// TODO: do anneal here
}
}
Loading

0 comments on commit ed2cadf

Please sign in to comment.