const BufferLayout = require("buffer-layout");
const sol = require("@solana/web3.js");
const fs = require('fs');
const cluster = sol.clusterApiUrl("devnet", true);
const programAddr = "2DvvSEde36Ch3B52g9hKWDYbfmJimLpJwVBV9Cknypi4"
let alice;
if (process.env.ALICE !== undefined) {
alice = sol.Keypair.fromSecretKey(
Buffer.from(JSON.parse(fs.readFileSync(process.env.ALICE, "utf-8"))));
} else {
alice = sol.Keypair.fromSecretKey(Buffer.from([97, 93, 122, 16, 225,
220, 239, 230, 206, 134, 241, 223, 228, 135, 202, 29, 7, 124, 108, 250,
96, 12, 103, 91, 103, 95, 201, 25, 156, 18, 98, 149, 89, 55, 40, 62, 196,
151, 180, 107, 249, 9, 23, 53, 215, 63, 170, 57, 173, 9, 36, 82, 233, 112,
55, 16, 15, 247, 47, 250, 115, 98, 210, 129]));
}
let bob;
if (process.env.BOB !== undefined) {
bob = sol.Keypair.fromSecretKey(
Buffer.from(JSON.parse(fs.readFileSync(process.env.BOB, "utf-8"))));
} else {
bob = sol.Keypair.fromSecretKey(Buffer.from([104, 59, 250, 44, 167,
108, 233, 202, 30, 232, 3, 91, 108, 141, 125, 241, 216, 86, 189, 157, 48,
69, 78, 98, 125, 6, 150, 127, 41, 214, 124, 242, 238, 189, 58, 189, 215,
194, 98, 74, 98, 184, 196, 38, 158, 174, 51, 135, 76, 147, 74, 61, 214,
178, 94, 233, 190, 216, 78, 115, 83, 39, 99, 226]));
}
function usage() {
console.log("usage: strfi.js [init|withdraw|cancel] [accountAddress (needed for withdraw/cancel)]");
process.exit(1);
}
const initLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
BufferLayout.u32("starttime"),
BufferLayout.u32("endtime"),
BufferLayout.nu64("amount"),
]);
const withdrawLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
BufferLayout.nu64("amount"),
]);
const cancelLayout = BufferLayout.struct([
BufferLayout.u8("instruction"),
]);
async function initStream(connection) {
now = Math.floor(new Date().getTime() / 1000);
var data = Buffer.alloc(initLayout.span);
initLayout.encode({
instruction: 0,
starttime: now + 10,
endtime: now + 610,
amount: 100000000,
},
data,
);
const pda = new sol.Keypair();
console.log("ALICE: %s", alice.publicKey.toBase58());
console.log("BOB: %s", bob.publicKey.toBase58());
console.log("PDA: %s", pda.publicKey.toBase58());
console.log("DATA:", data);
const instruction = new sol.TransactionInstruction({
keys: [{
pubkey: alice.publicKey,
isSigner: true,
isWritable: true,
}, {
pubkey: bob.publicKey,
isSigner: false,
isWritable: true,
}, {
pubkey: pda.publicKey,
isSigner: true,
isWritable: true,
}, {
pubkey: sol.SystemProgram.programId,
isSigner: false,
isWritable: false,
}],
programId: new sol.PublicKey(programAddr),
data: data,
});
tx = new sol.Transaction().add(instruction);
return await sol.sendAndConfirmTransaction(connection, tx, [alice, pda]);
}
async function withdrawStream(connection, accountAddr) {
var data = Buffer.alloc(withdrawLayout.span);
withdrawLayout.encode({
instruction: 1,
amount: 0,
},
data,
);
console.log("ALICE: %s", alice.publicKey.toBase58());
console.log("BOB: %s", bob.publicKey.toBase58());
console.log("PDA: %s", accountAddr);
console.log("DATA:", data);
const instruction = new sol.TransactionInstruction({
keys: [{
pubkey: bob.publicKey,
isSigner: true,
isWritable: true,
}, {
pubkey: new sol.PublicKey(accountAddr),
isSigner: false,
isWritable: true,
}, {
pubkey: new sol.PublicKey("DrFtxPb9F6SxpHHHFiEtSNXE3SZCUNLXMaHS6r8pkoz2"),
isSigner: false,
isWritable: true,
}, {
pubkey: sol.SystemProgram.programId,
isSigner: false,
isWritable: false,
}],
programId: new sol.PublicKey(programAddr),
data: data,
});
tx = new sol.Transaction().add(instruction);
return await sol.sendAndConfirmTransaction(connection, tx, [bob]);
}
async function cancelStream(connection, accountAddr) {
var data = Buffer.alloc(cancelLayout.span);
cancelLayout.encode({
instruction: 2,
},
data,
);
console.log("ALICE: %s", alice.publicKey.toBase58());
console.log("BOB: %s", bob.publicKey.toBase58());
console.log("PDA: %s", accountAddr);
console.log("DATA:", data);
const instruction = new sol.TransactionInstruction({
keys: [{
pubkey: alice.publicKey,
isSigner: true,
isWritable: true,
}, {
pubkey: bob.publicKey,
isSigner: false,
isWritable: true,
}, {
pubkey: new sol.PublicKey(accountAddr),
isSigner: false,
isWritable: true,
}, {
pubkey: sol.SystemProgram.programId,
isSigner: false,
isWritable: false,
}],
programId: new sol.PublicKey(programAddr),
data: data,
});
tx = new sol.Transaction().add(instruction);
return await sol.sendAndConfirmTransaction(connection, tx, [alice]);
}
async function main(args) {
if (process.argv.length < 3 || process.argv.length > 4) {
usage();
}
const conn = new sol.Connection(cluster);
switch (args[2]) {
case "init":
console.log("TXID:", await initStream(conn));
break;
case "withdraw":
if (args.length != 4) {
console.log("Missing metadata/funds account address");
usage();
}
console.log("TXID:", await withdrawStream(conn, args[3]));
break;
case "cancel":
if (args.length != 4) {
console.log("Missing metadata/funds account address");
usage();
}
console.log("TXID:", await cancelStream(conn, args[3]));
break;
default:
usage();
}
}
main(process.argv).then(() => process.exit(0)).catch(e => console.error(e));