Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ projects, controlled by a DAO.

## History

### 1. Initial release - Toucan NCT Buy-Burn-Fixxed
### 1. Initial release - Toucan NCT Buy-Burn-Fixed

The initial version of the Sunrise Yield Controller used the Buy-Burn-Fixed strategy to
distribute yield. This strategy was implemented in the `buy-burn-fixed` package.
Expand Down
57 changes: 49 additions & 8 deletions packages/tests/yieldRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,44 @@ describe("yield-router", () => {

context("create and update", () => {
it("can register a new yield router state", async () => {
const outputYieldAccounts = [Keypair.generate().publicKey];
const spendProportions = [100];
// setup
// where is the input?

const outputYieldAccounts = [
// create a new random public key
PublicKey.unique()
];
const spendProportions = [
// 100% of the yield is sent to this address
100
];

// act
client = await YieldRouterClient.register(
sunriseState,
authority.publicKey,
outputYieldAccounts,
spendProportions,
spendThreshold
);

// assert
// ???
});

it("should be updateable by the admin", async () => {
// setup
const outputYieldAccounts = [PublicKey.unique(), PublicKey.unique()];
const proportions = [30, 70];

// act
// the client is using the admin key
await client.updateOutputYieldAccounts(outputYieldAccounts, proportions);

const retrieved = await YieldRouterClient.fetch(client.stateAddress);
// assert
// get a new client instance
const yieldRouterStateAddress = client.stateAddress;
const retrieved = await YieldRouterClient.fetch(yieldRouterStateAddress);

expect(retrieved.config?.outputYieldAccounts).to.deep.equal(
outputYieldAccounts
Expand All @@ -55,20 +75,24 @@ describe("yield-router", () => {
});

it("should not be updateable by others", async () => {
const anotherUser = Keypair.generate();
const wallet = new Wallet(anotherUser);
// setup
// create a new user and give them some funds (so they can send transactions)
const unauthorisedUser = Keypair.generate();
const unauthorisedUserWallet = new Wallet(unauthorisedUser);
const connection = client.program.provider.connection;
const tx = await connection.requestAirdrop(
anotherUser.publicKey,
unauthorisedUser.publicKey,
LAMPORTS_PER_SOL
);
const blockhash = await connection.getLatestBlockhash();
await connection.confirmTransaction({ signature: tx, ...blockhash });

const provider = new AnchorProvider(connection, wallet, {});
// now the user has funds
// create a new yield router client for that user
const unauthorisedUserProvider = new AnchorProvider(connection, unauthorisedUserWallet, {});
const unauthorisedClient = await YieldRouterClient.fetch(
client.stateAddress,
provider
unauthorisedUserProvider
);

const shouldFail = unauthorisedClient.updateOutputYieldAccounts(
Expand All @@ -79,6 +103,7 @@ describe("yield-router", () => {
return expect(shouldFail).to.be.rejectedWith("Unauthorized.");
});

<<<<<<< HEAD
it("should be able to update with a new update authority", async () => {
// Setup
// Generate a new keypair that is going to be the new update authority
Expand Down Expand Up @@ -128,6 +153,22 @@ describe("yield-router", () => {
outputYieldAccounts
);
expect(retrieved.config?.spendProportions).to.deep.equal(proportions);
=======
it('should ...', () => {
const newKey = Keypair.generate();

const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: newKey.publicKey,
toPubkey: authority.publicKey,
lamports: 100_000,
})
)

transaction.sign(newKey);

console.log(transaction.signatures);
>>>>>>> 4b651c3 (Add code documentation)
});
});

Expand Down
23 changes: 19 additions & 4 deletions packages/yield-router/client/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export class YieldRouterClient {
}

private async init(): Promise<void> {
// ask anchor to get the contents of the account at the stateAddress
const state = await this.program.account.state.fetch(this.stateAddress);

this.config = {
Expand Down Expand Up @@ -103,10 +104,12 @@ export class YieldRouterClient {
stateAddress: PublicKey,
provider?: AnchorProvider
): Promise<InitialisedClient> {
// constructor is synchronous and does not retrieve information from the blockchain
const client = new YieldRouterClient(
provider ?? setUpAnchor(),
stateAddress
);
// retrieve the state from the chain
await client.init();

if (!client.config) {
Expand All @@ -115,16 +118,25 @@ export class YieldRouterClient {
return client as InitialisedClient;
}

/**
* Register a new yield router state on chain.
* This will typically happen only once.
* @param sunriseState
* @param updateAuthority
* @param outputYieldAccounts
* @param spendProportions
* @param spendThreshold
*/
public static async register(
sunriseState: PublicKey,
sunriseState: PublicKey, // (0)
updateAuthority: PublicKey,
outputYieldAccounts: PublicKey[],
spendProportions: number[],
spendThreshold: BN
): Promise<InitialisedClient> {
// find state address
const stateAddress =
await YieldRouterClient.getStateAddressFromSunriseAddress(sunriseState);
// find state address PDA (1)
const stateAddress = await YieldRouterClient.getStateAddressFromSunriseAddress(sunriseState);
// get input yield account PDA (2)
const inputYieldAccount = getInputYieldAccountForState(stateAddress);

const client = new YieldRouterClient(setUpAnchor(), stateAddress);
Expand All @@ -133,6 +145,7 @@ export class YieldRouterClient {
payer: client.provider.wallet.publicKey,
state: stateAddress,
inputYieldAccount,
// system program is used because we are instantiating a new account
systemProgram: SystemProgram.programId,
};

Expand All @@ -157,6 +170,7 @@ export class YieldRouterClient {
throw e;
});

// now that the state is registered on chain, we can hydrate the client instance with its data
await client.init();

return client as InitialisedClient;
Expand All @@ -172,6 +186,7 @@ export class YieldRouterClient {
const accounts = {
payer: this.provider.wallet.publicKey,
state: this.stateAddress,
// System program is needed because we may be resizing the state account
systemProgram: SystemProgram.programId,
};

Expand Down
1 change: 1 addition & 0 deletions programs/yield-router/src/utils/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub struct UpdateState<'info> {
#[account(
mut,
constraint = state.update_authority == payer.key() @ ErrorCode::Unauthorized,
// resize the state account if necessary
realloc = State::space(state_in.output_yield_accounts.len() as u8),
realloc::payer = payer,
realloc::zero = false,
Expand Down