solana-options
Version:
Minting of options contract NFTs on the Solana blockchain
252 lines (251 loc) • 18.5 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// import { SystemProgram } from "@solana/web3.js";
const web3_js_1 = require("@solana/web3.js");
const web3_js_2 = require("@solana/web3.js");
// import PrintClass from "jimp"
const chai_1 = require("chai");
// const expect = require('chai').expect;
const chai_2 = require("chai");
// var sinon = require("sinon");
// import {sinon} from "sinon"
const sinon_1 = __importDefault(require("sinon"));
const rewire_1 = __importDefault(require("rewire"));
let [sol_key, usd_key] = [new web3_js_1.Keypair().publicKey.toString(), new web3_js_1.Keypair().publicKey.toString()];
let sol_options = (0, rewire_1.default)("./");
const _1 = require(".");
const doc_1 = require("./doc");
const jimp_1 = __importDefault(require("jimp"));
const qrcode_1 = __importDefault(require("qrcode"));
// import { create_call, excercise_call, OptionType } from pack;
// pack.cre
// let [create_call, excercise_call, OptionType] = [sol_options.create_call, sol_options.exercise_call,sol_options.OptionType]
const programId = "4ktt843KtvduVq7yDdSXoTpt8uev4tBFue2pot7NdiRR";
const bob_private_key = [58, 61, 83, 12, 252, 164, 114, 167, 16, 61, 196, 241, 213, 70, 111, 76, 253, 145, 3, 249, 205, 251, 23, 52,
237, 158, 140, 188, 84, 202, 116, 216, 78, 242, 2, 9, 33, 177, 53, 200, 7, 221, 76, 53, 149, 13, 243, 125, 153, 187, 239, 178, 76,
197, 203, 88, 218, 186, 174, 108, 71, 19, 254, 203];
let creator_strike_instrument_acc = new web3_js_2.PublicKey('8Tv1h2eNjhfQJXyNR3Ey8WwoHAF1qZW7s7aNH49oCMBP');
let creator_instrument_acc = new web3_js_2.PublicKey("GsnpfUQTFnQBuokhttUajopkEeg4YNgwf7j2SSKhRigJ");
let creator_acc = web3_js_1.Keypair.fromSecretKey(new Uint8Array(bob_private_key));
const connection = new web3_js_2.Connection("http://localhost:8899", 'singleGossip');
// setup some stubs
let get_rent = sinon_1.default.fake();
sinon_1.default.replace(connection, "getMinimumBalanceForRentExemption", get_rent);
let confirm_tx = sinon_1.default.fake();
sinon_1.default.replace(connection, "confirmTransaction", confirm_tx);
let send_tx = sinon_1.default.fake();
sinon_1.default.replace(connection, "sendTransaction", send_tx);
const mocked_keypair = new web3_js_1.Keypair();
let find_address_stub = sinon_1.default.stub();
sinon_1.default.replace(web3_js_2.PublicKey, "findProgramAddress", find_address_stub);
find_address_stub.returns([mocked_keypair.publicKey, 42]);
afterEach(function () {
sinon_1.default.resetHistory();
});
describe('create call', function () {
it('create call contract using existing public keys without error', async function () {
let strike = 100;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_call)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
(0, chai_2.expect)(contract.instrument.toString()).to.equal(instrument.toString(), "inst value");
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(strike_instrument.toString(), "strike instr value");
// expect(contract.nft_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft id")
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
// expect(contract.account_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "account id")
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_strike_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(_1.OptionType.call);
(0, chai_2.expect)(send_tx.callCount).to.equal(1, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(2, "find address used twice");
}).catch();
});
it('create call contract using minted nft instrument without error', async function () {
let strike = 101;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
// let instrument = new PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf')
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_call)(connection, strike, expiry, multiple, creator_acc, null, strike_instrument, null, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
// expect(contract.instrument.toString()).to.equal(instrument.toString(), "inst value")
(0, chai_2.expect)(contract.instrument).to.be.a("object");
(0, chai_2.expect)(contract.instrument).to.be.ok;
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(strike_instrument.toString(), "strike instr value");
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_strike_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(_1.OptionType.call);
(0, chai_2.expect)(send_tx.callCount).to.equal(2, "tx sent only once");
(0, chai_2.expect)(confirm_tx.callCount).to.equal(1, "nft mint confirmed");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(4, "find address used twice");
}).catch();
});
it('create call contract using symbols without error', async function () {
let strike = 101;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
// let instrument = new PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf')
// let strike_instrument = new PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ')
let fake_tok_list = [{ symbol: "SOL", address: sol_key }, { symbol: "USDC", address: usd_key }];
sol_options.__set__("TOKEN_LIST", fake_tok_list);
console.log("using token list", fake_tok_list);
let [create_call, excercise_call, OptionType] = [sol_options.create_call, sol_options.exercise_call, sol_options.OptionType];
return create_call(connection, strike, expiry, multiple, creator_acc, "USDC", "SOL", creator_instrument_acc, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.instrument.toString()).to.be.equal(usd_key, "use USD token");
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(sol_key, "use SOL strike instr value");
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
(0, chai_2.expect)(contract.kind).to.equal(OptionType.call);
(0, chai_2.expect)(send_tx.callCount).to.equal(1, "tx sent only once");
(0, chai_2.expect)(confirm_tx.callCount).to.equal(0, "nft mint confirmed");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(2, "find address used twice");
}).catch();
});
it('create call contract using minted nft instrument and symbol strike instrument without error', async function () {
let strike = 101;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let fake_tok_list = [{ symbol: "SOL", address: sol_key }, { symbol: "USDC", address: usd_key }];
sol_options.__set__("TOKEN_LIST", fake_tok_list);
console.log("using token list", fake_tok_list);
let [create_call, excercise_call, OptionType] = [sol_options.create_call, sol_options.exercise_call, sol_options.OptionType];
return create_call(connection, strike, expiry, multiple, creator_acc, null, "SOL", null, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
// expect(contract.instrument.toString()).to.equal(instrument.toString(), "inst value")
(0, chai_2.expect)(contract.instrument).to.be.a("object");
(0, chai_2.expect)(contract.instrument).to.be.ok;
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(sol_key.toString(), "strike instr value");
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_strike_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(OptionType.call);
(0, chai_2.expect)(send_tx.callCount).to.equal(2, "tx sent only once");
(0, chai_2.expect)(confirm_tx.callCount).to.equal(1, "nft mint confirmed");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(4, "find address used twice");
}).catch();
});
it('create call contract then close it without error', async function () {
let strike = 100;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_call)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc).then(([sig, contract]) => {
return (0, _1.close_option)(connection, contract, creator_acc, creator_instrument_acc).then(sig => {
(0, chai_2.expect)(send_tx.callCount).to.equal(2, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(3, "find address used twice");
});
}).catch();
});
});
describe("create put", function () {
it('create put contract has correct receiving address', async function () {
let strike = 100;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_put)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
(0, chai_2.expect)(contract.instrument.toString()).to.equal(instrument.toString(), "inst value");
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(strike_instrument.toString(), "strike instr value");
// expect(contract.nft_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft id")
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
// expect(contract.account_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "account id")
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(_1.OptionType.put, "contract type");
(0, chai_2.expect)(send_tx.callCount).to.equal(1, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(2, "find address used twice");
}).catch();
});
});
describe("exercise contract", function () {
it('exercising a call contract ', async function () {
let strike = 100;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_call)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc).then(([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
(0, chai_2.expect)(contract.instrument.toString()).to.equal(instrument.toString(), "inst value");
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(strike_instrument.toString(), "strike instr value");
// expect(contract.nft_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft id")
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
// expect(contract.account_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "account id")
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_strike_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(_1.OptionType.call, "contract type");
(0, chai_2.expect)(send_tx.callCount).to.equal(1, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(2, "find address used twice");
let buyer_nft_acc = new web3_js_1.Keypair().publicKey;
let buyer_send_acc = new web3_js_1.Keypair().publicKey;
let buyer_receive_acc = new web3_js_1.Keypair().publicKey;
let buyer_acc = creator_acc;
return (0, _1.exercise_call)(connection, contract, buyer_acc, buyer_nft_acc, buyer_receive_acc, buyer_send_acc).then(sig => {
(0, chai_2.expect)(send_tx.callCount).to.equal(2, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(3, "find address used twice");
});
}).catch();
});
it('exercising an expired contract should fail ', async function () {
let strike = 100;
let expiry = Date.now() / 1000 - 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
return (0, _1.create_call)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc).then(async ([sig, contract]) => {
(0, chai_2.expect)(contract.strike).to.equal(strike, "strike value");
(0, chai_2.expect)(contract.expiry).to.equal(expiry);
(0, chai_2.expect)(contract.multiple).to.equal(multiple);
(0, chai_2.expect)(contract.instrument.toString()).to.equal(instrument.toString(), "inst value");
(0, chai_2.expect)(contract.strike_instrument.toString()).to.equal(strike_instrument.toString(), "strike instr value");
// expect(contract.nft_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft id")
(0, chai_2.expect)(contract.nft_account.toString()).to.equal(mocked_keypair.publicKey.toString(), "nft account");
// expect(contract.account_id.toString()).to.equal(mocked_keypair.publicKey.toString(), "account id")
(0, chai_2.expect)(contract.writer_recv_acc).to.equal(creator_strike_instrument_acc, "receiving acc");
(0, chai_2.expect)(contract.kind).to.equal(_1.OptionType.call, "contract type");
(0, chai_2.expect)(send_tx.callCount).to.equal(1, "tx sent only once");
(0, chai_2.expect)(find_address_stub.callCount).to.equal(2, "find address used twice");
let buyer_nft_acc = new web3_js_1.Keypair().publicKey;
let buyer_send_acc = new web3_js_1.Keypair().publicKey;
let buyer_receive_acc = new web3_js_1.Keypair().publicKey;
let buyer_acc = creator_acc;
return (0, _1.exercise_call)(connection, contract, buyer_acc, buyer_nft_acc, buyer_receive_acc, buyer_send_acc).then(async (sig) => {
chai_1.assert.fail("expire contract should not be exercised");
}).catch(err => {
(0, chai_2.expect)(err).to.be.equal("contract has exipired");
});
}).catch(err => {
chai_1.assert.fail(err);
});
});
});
describe("create contract doc", function () {
this.timeout(60000);
it('create put contract doc', async function () {
let strike = 100;
let expiry = Date.now() / 1000 + 600;
let multiple = 1000000000;
let instrument = new web3_js_2.PublicKey('D3KCKMTY8rgWtVmxKdCeugKEFbJMjSHk7iWiLMAKrrMf');
let strike_instrument = new web3_js_2.PublicKey('6Uhbk6FwCLLQfsKJ8kn8uCsiF5iZNVQDw5QxMNJh9XiJ');
let font_spy = sinon_1.default.spy(jimp_1.default, "loadFont");
let qrcode_spy = sinon_1.default.spy(qrcode_1.default, "toDataURL");
const [sig, contract] = await (0, _1.create_put)(connection, strike, expiry, multiple, creator_acc, instrument, strike_instrument, creator_instrument_acc, creator_strike_instrument_acc);
const img = await (0, doc_1.create_doc_img)(contract);
(0, chai_2.expect)(font_spy.callCount).to.equal(1);
(0, chai_2.expect)(qrcode_spy.callCount).to.equal(1);
});
});