diff --git a/README.md b/README.md index 35c522c1..fb83a5ff 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ Using the CashScript SDK, you can import / compile existing cash contract files, ```ts ... // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), 'testnet'); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), 'testnet'); // Instantiate a new P2PKH contract with constructor arguments: { pkh: pkh } const instance: Instance = P2PKH.new(pkh); diff --git a/examples/Escrow/Escrow.ts b/examples/Escrow/Escrow.ts index 790fcb4b..ee356edb 100644 --- a/examples/Escrow/Escrow.ts +++ b/examples/Escrow/Escrow.ts @@ -59,10 +59,7 @@ export async function run(): Promise { const oracle: Oracle = new Oracle(bitbox.HDNode.toKeyPair(alice)); // Compile and instantiate Escrow contract - const Escrow: Contract = Contract.fromCashFile( - path.join(__dirname, 'Escrow.cash'), - network, - ); + const Escrow: Contract = Contract.compile(path.join(__dirname, 'Escrow.cash'), network); const escrowKey: Buffer = Buffer.from('01', 'hex'); const actionByte: Buffer = Buffer.from('01', 'hex'); const instance: Instance = Escrow.new( diff --git a/examples/hodl_vault.ts b/examples/hodl_vault.ts index 0cf3f340..15729d6c 100644 --- a/examples/hodl_vault.ts +++ b/examples/hodl_vault.ts @@ -22,7 +22,7 @@ export async function run(): Promise { ); // Compile and instantiate HODL Vault - const HodlVault: Contract = Contract.fromCashFile(path.join(__dirname, 'hodl_vault.cash'), 'testnet'); + const HodlVault: Contract = Contract.compile(path.join(__dirname, 'hodl_vault.cash'), 'testnet'); const instance: Instance = HodlVault.new( bitbox.ECPair.toPublicKey(owner), bitbox.ECPair.toPublicKey(oracle.keypair), diff --git a/examples/meep.ts b/examples/meep.ts index adc89090..3cf0195e 100644 --- a/examples/meep.ts +++ b/examples/meep.ts @@ -19,7 +19,7 @@ export async function run(): Promise { const alicePkh: Buffer = bitbox.Crypto.hash160(alicePk); // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), network); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } const instance: Instance = P2PKH.new(alicePkh); diff --git a/examples/memo_cash.ts b/examples/memo_cash.ts index 3f24f894..fd05170c 100644 --- a/examples/memo_cash.ts +++ b/examples/memo_cash.ts @@ -20,7 +20,7 @@ export async function run(): Promise { const alicePkh: Buffer = bitbox.Crypto.hash160(alicePk); // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), network); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } const instance: Instance = P2PKH.new(alicePkh); diff --git a/examples/p2pkh-artifact.ts b/examples/p2pkh-artifact.ts index 5f0dbc57..eb9473ac 100644 --- a/examples/p2pkh-artifact.ts +++ b/examples/p2pkh-artifact.ts @@ -20,7 +20,7 @@ export async function run(): Promise { const alicePkh: Buffer = bitbox.Crypto.hash160(alicePk); // Import the P2PKH Cash Contract from Artifact file, including deployed contract details - const P2PKH: Contract = Contract.fromArtifact(path.join(__dirname, 'p2pkh.json'), network); + const P2PKH: Contract = Contract.import(path.join(__dirname, 'p2pkh.json'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } let instance: Instance = P2PKH.new(alicePkh); diff --git a/examples/p2pkh.js b/examples/p2pkh.js index 5f17fc6d..f2ddfbf5 100644 --- a/examples/p2pkh.js +++ b/examples/p2pkh.js @@ -18,7 +18,7 @@ async function run() { const alicePkh = bitbox.Crypto.hash160(alicePk); // Compile the P2PKH Cash Contract - const P2PKH = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), network); + const P2PKH = Contract.compile(path.join(__dirname, 'p2pkh.cash'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } const instance = P2PKH.new(alicePkh); diff --git a/examples/p2pkh.ts b/examples/p2pkh.ts index 24a80499..0efca597 100644 --- a/examples/p2pkh.ts +++ b/examples/p2pkh.ts @@ -20,7 +20,7 @@ export async function run(): Promise { const alicePkh: Buffer = bitbox.Crypto.hash160(alicePk); // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), network); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } const instance: Instance = P2PKH.new(alicePkh); diff --git a/examples/slp_genesis.ts b/examples/slp_genesis.ts index d03a4eea..66cf3a58 100644 --- a/examples/slp_genesis.ts +++ b/examples/slp_genesis.ts @@ -20,7 +20,7 @@ export async function run(): Promise { const alicePkh: Buffer = bitbox.Crypto.hash160(alicePk); // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), network); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), network); // Instantiate a new P2PKH contract with constructor arguments: { pkh: alicePkh } const instance: Instance = P2PKH.new(alicePkh); diff --git a/examples/transfer_with_timeout.ts b/examples/transfer_with_timeout.ts index f53a6a5b..088b220d 100644 --- a/examples/transfer_with_timeout.ts +++ b/examples/transfer_with_timeout.ts @@ -23,7 +23,7 @@ export async function run(): Promise { const bobPk: Buffer = bitbox.ECPair.toPublicKey(bob); // Compile the TransferWithTimeout Cash Contract - const TransferWithTimeout: Contract = Contract.fromCashFile( + const TransferWithTimeout: Contract = Contract.compile( path.join(__dirname, 'transfer_with_timeout.cash'), network, ); diff --git a/packages/cashscript/README.md b/packages/cashscript/README.md index 994627d2..f0f030a0 100644 --- a/packages/cashscript/README.md +++ b/packages/cashscript/README.md @@ -39,7 +39,7 @@ Using the CashScript SDK, you can import / compile existing cash contract files, ```ts ... // Compile the P2PKH Cash Contract - const P2PKH: Contract = Contract.fromCashFile(path.join(__dirname, 'p2pkh.cash'), 'testnet'); + const P2PKH: Contract = Contract.compile(path.join(__dirname, 'p2pkh.cash'), 'testnet'); // Instantiate a new P2PKH contract with constructor arguments: { pkh: pkh } const instance: Instance = P2PKH.new(pkh); diff --git a/packages/cashscript/src/Contract.ts b/packages/cashscript/src/Contract.ts index 5ef10233..0f1be22c 100644 --- a/packages/cashscript/src/Contract.ts +++ b/packages/cashscript/src/Contract.ts @@ -4,6 +4,7 @@ import { CashCompiler, Data, } from 'cashc'; +import * as fs from 'fs'; import { Transaction } from './Transaction'; import { Instance } from './Instance'; import { Parameter, encodeParameter, Sig } from './Parameter'; @@ -13,18 +14,35 @@ export class Contract { new: (...params: Parameter[]) => Instance; deployed: (at?: string) => Instance; - static fromCashFile(fn: string, network?: string): Contract { - const artifact = CashCompiler.compileFile(fn); + static compile(fnOrString: string, network?: string): Contract { + const artifact = fs.existsSync(fnOrString) + ? CashCompiler.compileFile(fnOrString) + : CashCompiler.compileString(fnOrString); + return new Contract(artifact, network); } - static fromArtifact(fn: string, network?: string): Contract { - const artifact = Artifacts.require(fn); + static import(fnOrArtifact: string | Artifact, network?: string): Contract { + const artifact = typeof fnOrArtifact === 'string' + ? Artifacts.require(fnOrArtifact) + : fnOrArtifact; + return new Contract(artifact, network); } - export(fn: string): void { - Artifacts.export(this.artifact, fn); + // @deprecated + static fromCashFile(fnOrString: string, network?: string): Contract { + return this.compile(fnOrString, network); + } + + // @deprecated + static fromArtifact(fnOrArtifact: string | Artifact, network?: string): Contract { + return this.import(fnOrArtifact, network); + } + + export(fn?: string): Artifact { + if (typeof fn !== 'undefined') Artifacts.export(this.artifact, fn); + return this.artifact; } constructor( diff --git a/packages/cashscript/test/Contract.test.ts b/packages/cashscript/test/Contract.test.ts index 27f4e9cb..a0ff9f35 100644 --- a/packages/cashscript/test/Contract.test.ts +++ b/packages/cashscript/test/Contract.test.ts @@ -3,16 +3,30 @@ import * as path from 'path'; import { Contract, Artifacts } from '../src'; describe('Contract', () => { - describe('fromCashFile', () => { - it('should fail for invalid .cash file', () => { + describe('compile', () => { + it('should fail for invalid .cash file or string', () => { assert.throws(() => { - Contract.fromCashFile(path.join(__dirname, 'fixture', 'p2pkh-invalid.cash')); + Contract.compile(path.join(__dirname, 'fixture', 'p2pkh-invalid.cash')); }); + + assert.throws(() => { + Contract.compile('contract P2PKH(bytes20 pkh) {\n // Require pk to match stored pkh and signature to match\n functon spend(pubkey pk, sig s) {\n require(hash160(pk) == pkh);\n require(checkSig(s, pk));\n }\n}\n'); + }); + }); + + it('should create P2PKH Contract object from file', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh.json')); + const P2PKH = Contract.compile(path.join(__dirname, 'fixture', 'p2pkh.cash')); + + // Disregard updatedAt & networks + expectedArtifact.updatedAt = P2PKH.artifact.updatedAt; + expectedArtifact.networks = P2PKH.artifact.networks; + assert.deepEqual(P2PKH.artifact, expectedArtifact); }); - it('should create P2PKH Contract object', () => { - const P2PKH = Contract.fromCashFile(path.join(__dirname, 'fixture', 'p2pkh.cash')); + it('should create P2PKH Contract object from string', () => { const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh.json')); + const P2PKH = Contract.compile(expectedArtifact.source); // Disregard updatedAt & networks expectedArtifact.updatedAt = P2PKH.artifact.updatedAt; @@ -20,9 +34,19 @@ describe('Contract', () => { assert.deepEqual(P2PKH.artifact, expectedArtifact); }); - it('should create TransferWithTimeout Contract object', () => { - const TransferWithTimeout = Contract.fromCashFile(path.join(__dirname, 'fixture', 'transfer_with_timeout.cash')); + it('should create TransferWithTimeout Contract object from file', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'transfer_with_timeout.json')); + const TransferWithTimeout = Contract.compile(path.join(__dirname, 'fixture', 'transfer_with_timeout.cash')); + + // Disregard updatedAt & networks + expectedArtifact.updatedAt = TransferWithTimeout.artifact.updatedAt; + expectedArtifact.networks = TransferWithTimeout.artifact.networks; + assert.deepEqual(TransferWithTimeout.artifact, expectedArtifact); + }); + + it('should create TransferWithTimeout Contract object from string', () => { const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'transfer_with_timeout.json')); + const TransferWithTimeout = Contract.compile(expectedArtifact.source); // Disregard updatedAt & networks expectedArtifact.updatedAt = TransferWithTimeout.artifact.updatedAt; @@ -30,9 +54,19 @@ describe('Contract', () => { assert.deepEqual(TransferWithTimeout.artifact, expectedArtifact); }); + it('should create HodlVault Contract object from file', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'hodl_vault.json')); + const HodlVault = Contract.compile(path.join(__dirname, 'fixture', 'hodl_vault.cash')); + + // Disregard updatedAt & networks + expectedArtifact.updatedAt = HodlVault.artifact.updatedAt; + expectedArtifact.networks = HodlVault.artifact.networks; + assert.deepEqual(HodlVault.artifact, expectedArtifact); + }); + it('should create HodlVault Contract object', () => { - const HodlVault = Contract.fromCashFile(path.join(__dirname, 'fixture', 'hodl_vault.cash')); const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'hodl_vault.json')); + const HodlVault = Contract.compile(expectedArtifact.source); // Disregard updatedAt & networks expectedArtifact.updatedAt = HodlVault.artifact.updatedAt; @@ -41,30 +75,56 @@ describe('Contract', () => { }); }); - describe('fromArtifact', () => { - it('should fail with invalid Artifact file', () => { + describe('import', () => { + it('should fail with invalid Artifact file or object', () => { assert.throws(() => { - Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh-invalid.json'), 'testnet'); + Contract.import(path.join(__dirname, 'fixture', 'p2pkh-invalid.json'), 'testnet'); }); + assert.throws(() => { + const artifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh-invalid.json')); + artifact.abi = []; + Contract.import(artifact); + }); + }); + + it('should create P2PKH Contract object from file', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh.json')); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + + assert.deepEqual(P2PKH.artifact, expectedArtifact); }); - it('should create P2PKH Contract object', () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + it('should create P2PKH Contract object from object', () => { const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh.json')); + const P2PKH = Contract.import(expectedArtifact, 'testnet'); assert.deepEqual(P2PKH.artifact, expectedArtifact); }); - it('should create TransferWithTimeout Contract object', () => { - const TransferWithTimeout = Contract.fromArtifact(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); + it('should create TransferWithTimeout Contract object from file', () => { const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'transfer_with_timeout.json')); + const TransferWithTimeout = Contract.import(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); assert.deepEqual(TransferWithTimeout.artifact, expectedArtifact); }); - it('should create HodlVault Contract object', () => { - const HodlVault = Contract.fromArtifact(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); + it('should create TransferWithTimeout Contract object from object', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'transfer_with_timeout.json')); + const TransferWithTimeout = Contract.import(expectedArtifact, 'testnet'); + + assert.deepEqual(TransferWithTimeout.artifact, expectedArtifact); + }); + + it('should create HodlVault Contract object from file', () => { + const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'hodl_vault.json')); + const HodlVault = Contract.import(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); + + assert.deepEqual(HodlVault.artifact, expectedArtifact); + }); + + it('should create HodlVault Contract object from object', () => { const expectedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'hodl_vault.json')); + const HodlVault = Contract.import(expectedArtifact, 'testnet'); assert.deepEqual(HodlVault.artifact, expectedArtifact); }); @@ -72,17 +132,25 @@ describe('Contract', () => { describe('export', () => { it('should export Artifact file', () => { - const initial = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); - initial.export(path.join(__dirname, 'fixture', 'p2pkh.json')); + const initial = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const returnedArtifact = initial.export(path.join(__dirname, 'fixture', 'p2pkh.json')); const exportedArtifact = Artifacts.require(path.join(__dirname, 'fixture', 'p2pkh.json')); assert.deepEqual(initial.artifact, exportedArtifact); + assert.deepEqual(initial.artifact, returnedArtifact); + }); + + it('should export Artifact object', () => { + const initial = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const artifact = initial.export(); + + assert.deepEqual(initial.artifact, artifact); }); }); describe('new', () => { it('should fail with incorrect constructor parameters', () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); assert.throws(() => { P2PKH.new(); @@ -102,7 +170,7 @@ describe('Contract', () => { }); it('should create new P2PKH instance', () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); const instance = P2PKH.new(Buffer.alloc(20, 0)); @@ -112,7 +180,7 @@ describe('Contract', () => { }); it('should create new TransferWithTimeout instance', () => { - const TransferWithTimeout = Contract.fromArtifact(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); + const TransferWithTimeout = Contract.import(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); const instance = TransferWithTimeout.new(Buffer.alloc(65, 0), Buffer.alloc(65, 0), 1000000); @@ -123,7 +191,7 @@ describe('Contract', () => { }); it('should create new HodlVault instance', () => { - const HodlVault = Contract.fromArtifact(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); + const HodlVault = Contract.import(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); const instance = HodlVault.new(Buffer.alloc(65, 0), Buffer.alloc(65, 0), 1000000, 10000); @@ -135,7 +203,7 @@ describe('Contract', () => { describe('deployed', () => { it('should fail on new Contract', () => { - const P2PKH = Contract.fromCashFile(path.join(__dirname, 'fixture', 'p2pkh.cash'), 'testnet'); + const P2PKH = Contract.compile(path.join(__dirname, 'fixture', 'p2pkh.cash'), 'testnet'); assert.isEmpty(P2PKH.artifact.networks); assert.throws(() => { @@ -147,7 +215,7 @@ describe('Contract', () => { }); it('should return deployed P2PKH', () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); const deployedAddress = 'bchtest:pzfsp649y00eay9mm3ky63ln72v3h6tx6gul8mlg93'; assert.isNotEmpty(P2PKH.artifact.networks); diff --git a/packages/cashscript/test/Instance.test.ts b/packages/cashscript/test/Instance.test.ts index f3bf9238..3595fda7 100644 --- a/packages/cashscript/test/Instance.test.ts +++ b/packages/cashscript/test/Instance.test.ts @@ -13,7 +13,7 @@ describe('Instance', () => { describe('getBalance', () => { // Not very robust, as this depends on the example P2PKH contract having balance it('should return balance for existing contract', async () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); const instance = P2PKH.deployed(); const otherInstance = P2PKH.new(alicePkh); @@ -22,7 +22,7 @@ describe('Instance', () => { }); it('should return zero balance for new contract', async () => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); const instance = P2PKH.new(Buffer.alloc(20, 0)); assert.equal(await instance.getBalance(), 0); @@ -33,9 +33,9 @@ describe('Instance', () => { let instance: Instance; let bbInstance: Instance; beforeEach(() => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); instance = P2PKH.deployed(); - const BoundedBytes = Contract.fromArtifact(path.join(__dirname, 'fixture', 'bounded_bytes.json'), 'testnet'); + const BoundedBytes = Contract.import(path.join(__dirname, 'fixture', 'bounded_bytes.json'), 'testnet'); bbInstance = BoundedBytes.new(); }); diff --git a/packages/cashscript/test/Transaction.test.ts b/packages/cashscript/test/Transaction.test.ts index 48077958..462b2698 100644 --- a/packages/cashscript/test/Transaction.test.ts +++ b/packages/cashscript/test/Transaction.test.ts @@ -26,7 +26,7 @@ describe('Transaction', () => { describe('P2PKH', () => { let p2pkhInstance: Instance; before(() => { - const P2PKH = Contract.fromArtifact(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); + const P2PKH = Contract.import(path.join(__dirname, 'fixture', 'p2pkh.json'), 'testnet'); p2pkhInstance = P2PKH.new(alicePkh); }); @@ -156,7 +156,7 @@ describe('Transaction', () => { let twtInstancePast: Instance; let twtInstanceFuture: Instance; before(() => { - const TWT = Contract.fromArtifact(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); + const TWT = Contract.import(path.join(__dirname, 'fixture', 'transfer_with_timeout.json'), 'testnet'); twtInstancePast = TWT.new(alicePk, bobPk, 1000000); twtInstanceFuture = TWT.new(alicePk, bobPk, 2000000); }); @@ -391,7 +391,7 @@ describe('Transaction', () => { describe('HodlVault', () => { let hodlVault: Instance; before(() => { - const HodlVault = Contract.fromArtifact(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); + const HodlVault = Contract.import(path.join(__dirname, 'fixture', 'hodl_vault.json'), 'testnet'); hodlVault = HodlVault.new(alicePk, oraclePk, 597000, 30000); }); @@ -517,7 +517,7 @@ describe('Transaction', () => { describe('BoundedBytes', () => { let bbInstance: Instance; before(() => { - const BoundedBytes = Contract.fromArtifact(path.join(__dirname, 'fixture', 'bounded_bytes.json'), 'testnet'); + const BoundedBytes = Contract.import(path.join(__dirname, 'fixture', 'bounded_bytes.json'), 'testnet'); bbInstance = BoundedBytes.new(); });