@depay/web3-mock
Version:
JavaScript library to mock web3 responses either by emulating web3 wallets or web3 RPC requests.
1,265 lines (1,086 loc) • 51.8 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('ethers'), require('@depay/solana-web3.js'), require('@depay/web3-blockchains')) :
typeof define === 'function' && define.amd ? define(['exports', 'ethers', '@depay/solana-web3.js', '@depay/web3-blockchains'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Web3Mock = {}, global.ethers, global.SolanaWeb3js, global.Web3Blockchains));
}(this, (function (exports, ethers, solanaWeb3_js, Blockchains) { 'use strict';
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var Blockchains__default = /*#__PURE__*/_interopDefaultLegacy(Blockchains);
let currentBlock;
let blockData = {};
let getCurrentBlock = () => {
return currentBlock
};
let resetCurrentBlock = ()=>{
currentBlock = 1;
};
resetCurrentBlock();
let increaseBlock = (amount = 1) => {
currentBlock += amount;
};
let setBlockData = (number, data) => {
blockData[number] = data;
};
let resetBlockData = ()=> {
blockData = {};
};
let confirm$1 = (transaction) => {
transaction._confirmedAtBlock = getCurrentBlock();
return transaction
};
var raise = (msg)=>{
console.log(msg);
throw(msg)
};
function _optionalChain$b(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }let getWindow = (configuration) => {
if (_optionalChain$b([configuration, 'optionalAccess', _ => _.window])) return configuration.window
if (typeof global == 'object') return global
if (typeof cy == 'object') return cy.window().specWindow.window
if (typeof window == 'object') return window
};
let required = [];
let requireMock = (type) => {
required.push(type);
};
let resetRequire = () => {
required = [];
};
let count = {};
let increaseTransactionCount = (address) => {
address = address.toLowerCase();
if(count[address] == undefined) { count[address] = 0; }
count[address] += 1;
};
let getTransactionCount = (address) => {
address = address.toLowerCase();
if(count[address] == undefined) { count[address] = 0; }
return ethers.ethers.BigNumber.from(count[address].toString())._hex
};
let resetTransactionCount = ()=> {
count = {};
};
let WalletConnectClass, WalletLinkClass;
let mocks = [];
const setWalletConnectClass = (givenWalletConnectClass)=> {
WalletConnectClass = givenWalletConnectClass;
};
const setWalletLinkClass = (givenWalletLinkClass)=> {
WalletLinkClass = givenWalletLinkClass;
};
const resetMocks = ()=> {
let window = getWindow();
if (window.ethereum) {
window.ethereum = undefined;
}
mocks = [];
resetRequire();
resetCurrentBlock();
resetBlockData();
resetTransactionCount();
if(WalletConnectClass) { WalletConnectClass.instance = undefined; }
if(WalletLinkClass) { WalletLinkClass.instance = undefined; }
};
resetMocks();
let supported = ['solana'];
supported.evm = [];
supported.svm = ['solana'];
function _optionalChain$a(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var confirm = (mock) => {
if (_optionalChain$a([mock, 'optionalAccess', _ => _.transaction, 'optionalAccess', _2 => _2._id])) {
mock.transaction._confirmed = true;
if(supported.evm.includes(mock.blockchain)) ; else if(supported.svm.includes(mock.blockchain)) {
confirm$1(mock.transaction);
} else {
raise('Web3Mock: Unknown blockchain!');
}
increaseBlock();
} else {
raise('Web3Mock: Given mock is not a sent transaction: ' + JSON.stringify(mock));
}
};
var to_b58 = function(
B, //Uint8Array raw byte input
A //Base58 characters (i.e. "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
) {
var d = [], //the array for storing the stream of base58 digits
s = "", //the result string variable that will be returned
i, //the iterator variable for the byte input
j, //the iterator variable for the base58 digit array (d)
c, //the carry amount variable that is used to overflow from the current base58 digit to the next base58 digit
n; //a temporary placeholder variable for the current base58 digit
for(i in B) { //loop through each byte in the input stream
j = 0, //reset the base58 digit iterator
c = B[i]; //set the initial carry amount equal to the current byte amount
s += c || s.length ^ i ? "" : 1; //prepend the result string with a "1" (0 in base58) if the byte stream is zero and non-zero bytes haven't been seen yet (to ensure correct decode length)
while(j in d || c) { //start looping through the digits until there are no more digits and no carry amount
n = d[j]; //set the placeholder for the current base58 digit
n = n ? n * 256 + c : c; //shift the current base58 one byte and add the carry amount (or just add the carry amount if this is a new digit)
c = n / 58 | 0; //find the new carry amount (floored integer of current digit divided by 58)
d[j] = n % 58; //reset the current base58 digit to the remainder (the carry amount will pass on the overflow)
j++; //iterate to the next base58 digit
}
}
while(j--) //since the base58 digits are backwards, loop through them in reverse order
s += A[d[j]]; //lookup the character associated with each base58 digit
return s //return the final base58 string
};
const getRandomTransactionHash = (blockchain) => {
if(supported.evm.includes(blockchain)) {
return ethers.ethers.BigNumber.from(
'1' +
Array(76)
.fill()
.map(() => Math.random().toString()[4])
.join(''),
)._hex
} else if (supported.svm.includes(blockchain)) {
return to_b58(
Array(32)
.fill()
.map(() => parseInt(Math.random().toString()[4]), 10),
"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
)
}
};
var replace = (transactionMock, replacingTransactionMock, confirmed = true) => {
if(transactionMock == undefined || replacingTransactionMock == undefined) { raise('replace requires (transactionMock, replacingTransactionMock)'); }
if(transactionMock.transaction.from == undefined) { raise('transactionMock to be replaced requires at least a "from"'); }
replacingTransactionMock.transaction._id = getRandomTransactionHash(replacingTransactionMock.blockchain);
if(confirmed){
replacingTransactionMock.transaction._confirmed = true;
} else {
replacingTransactionMock.transaction._failed = true;
}
setBlockData(getCurrentBlock(), {
"number": "0xd6fa38",
"baseFeePerGas": "0x2d79336308",
"difficulty": "0x2ca5a8551de6c9",
"extraData": "0x6575726f70652d63656e7472616c322d33",
"gasLimit": "0x1ca35d2",
"gasUsed": "0x4f1487",
"hash": "0x8110e001148adad4d749559998e82061aa7d11bfdab65b840608327f98550fbc",
"logsBloom": "0x04200102130400839382604c8300800e003008904824c0060100214904200e03012450500400101050704850004005208a028000092171092200140020202001c24221a08488114c08a4000c844008340024058014408121408021d1c04401011320800023240000031050205300088921155204008186203102141410180102d840890204a0d202001801070004003010060011030081090000044800100e0462580e48280221000a2020d0801186a80001800922060000506288a092c81814c1482202402041882514000204008800c00c3300044900102860814e088221219411248a86440000020017c104088b10404180012100004000011892002004b8",
"miner": "0xea674fdde714fd979de3edf0f56aa9716b898ec8",
"mixHash": "0x3c18abd91830b37cab8451afbbfb480de19bfc43e6cb9dea4b2eac1c41c81c2b",
"nonce": "0x41fdf9e14a45d935",
"parentHash": "0x885327d9913d7effef8532b5ee0815b1711a279b3414da90b93f175135701803",
"receiptsRoot": "0x605fecc910c7e00a244da10635b170f7eabded9449321e79b73e42eb82619747",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x6e63",
"stateRoot": "0xc5549451a31830f2cbba18453066f9ef7539243f58ee1340341d1376a87ffd56",
"timestamp": "0x61f2c7ec",
"totalDifficulty": "0x87820e2f3a1f8913fee",
"transactionsRoot": "0x5582fa18ef2f1eb6a4f3ca7d225b9fb1050074293cd30127ef3919a35fd50d2b",
"uncles": [],
transactions: [
{
"hash": replacingTransactionMock.transaction._id,
"accessList": [],
"blockHash": "0x8110e001148adad4d749559998e82061aa7d11bfdab65b840608327f98550fbc",
"blockNumber": "0xd6fa38",
"from": replacingTransactionMock.transaction.from,
"gas": "0x55730",
"gasPrice": "0x2d79336308",
"input": "0x8803dbee0000000000000000000000000000000000000000001782b76fd64557b6b780000000000000000000000000000000000000000000000000032a27fd31187d551000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000008817d887960737a604cf712d3e5da8673dddb7f00000000000000000000000000000000000000000000000000000000061f2ca440000000000000000000000000000000000000000000000000000000000000002000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000090185f2135308bad17527004364ebcc2d37e5f6",
"maxFeePerGas": "0x2e87159fb3",
"maxPriorityFeePerGas": "0x0",
"nonce": getTransactionCount(replacingTransactionMock.transaction.from),
"r": "0x81d4fe714af2e1725ad1746fc240a6ac3b0f795d207ac207f36abaf8db6c72b2",
"s": "0x3c4f61eef2ecb98a50bf3940bc90e7dcacbc7f233a57d5eb44c0ae07fdec4ced",
"to": replacingTransactionMock.transaction.to,
"transactionIndex": "0x0",
"type": "0x2",
"v": "0x0",
"value": "0x0"
}
]
});
increaseBlock();
increaseTransactionCount(transactionMock.transaction.from);
};
let fail$1 = (transaction, reason) => {
transaction._confirmedAtBlock = getCurrentBlock();
transaction._failed = true;
transaction._failedReason = reason;
return transaction
};
function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
var fail = (mock, reason) => {
if (_optionalChain$9([mock, 'optionalAccess', _ => _.transaction, 'optionalAccess', _2 => _2._id])) {
mock.transaction._failed = true;
mock.transaction._confirmed = false;
if(supported.evm.includes(mock.blockchain)) ; else if(supported.svm.includes(mock.blockchain)) {
fail$1(mock.transaction, reason);
} else {
raise('Web3Mock: Unknown blockchain!');
}
increaseBlock();
} else {
raise('Web3Mock: Given mock is not a sent transaction: ' + JSON.stringify(mock));
}
};
function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }let normalize = function (input) {
if (input instanceof Array) {
return input.map((element) => normalize(element))
} else if (typeof input === 'undefined') {
return input
} else if (typeof input === 'object' && input._isBigNumber) {
return input.toString()
} else {
if (_optionalChain$8([input, 'optionalAccess', _ => _.toString])) {
return input.toString().toLowerCase()
} else if (typeof input === 'object') {
return JSON.stringify(input)
} else if (typeof input === 'string' && input.match('0x')) {
return input.toLowerCase()
} else {
return input
}
}
};
let anything = '__ANYTHING__';
function _optionalChain$7(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let mockIsNotAnObject = (mock) => {
return typeof mock !== 'object'
};
let mockHasWrongType = (mock, type) => {
return mock[type] == undefined
};
let mockHasWrongMethod = (mock, method) => {
if(mock.request && mock.request.method) { return mock.request.method != method }
return false
};
let mockHasWrongBlockchain = (mock, blockchain) => {
if(blockchain == undefined) { return false }
return mock.blockchain != blockchain
};
let mockHasWrongProvider = (mock, provider) => {
if(mock.provider == undefined) { return false }
return mock.provider != provider
};
let mockHasWrongTransactionData = (mock, type, transaction) => {
let requiredFrom = _optionalChain$7([transaction, 'optionalAccess', _ => _.message, 'optionalAccess', _2 => _2.staticAccountKeys, 'optionalAccess', _3 => _3.length]) ? transaction.message.staticAccountKeys[0].toString() : undefined;
return (
(mock[type].from && normalize(requiredFrom) !== normalize(mock[type].from))
)
};
let mockInstructionsMatch = (mockedInstruction, instruction)=>{
if(_optionalChain$7([mockedInstruction, 'optionalAccess', _4 => _4.params]) == anything) { return true }
if(!mockedInstruction.params) { return true }
let decodedInstructionData;
try { decodedInstructionData = mockedInstruction.api.decode(instruction.data); } catch (e) {}
if(!decodedInstructionData) { return false }
return Object.keys(mockedInstruction.params).every((key)=>{
if(mockedInstruction.params[key] == anything) { return true }
return normalize(mockedInstruction.params[key]) == normalize(decodedInstructionData[key])
})
};
let mockKeysMatch = (mockedInstruction, instruction, transaction)=>{
if(_optionalChain$7([mockedInstruction, 'optionalAccess', _5 => _5.keys]) == anything) { return true }
if(!mockedInstruction.keys || mockedInstruction.keys.length === 0) { return true }
return mockedInstruction.keys.every((mockedKey, index)=>{
if(mockedKey === anything) { return true }
return(
mockedKey.pubkey.toString() === transaction.message.staticAccountKeys[instruction.accountKeyIndexes[index]].toString()
)
})
};
let mockHasWrongTransactionInstructions = (mock, type, transaction) => {
return (
(_optionalChain$7([mock, 'access', _6 => _6[type], 'optionalAccess', _7 => _7.instructions]) && mock[type].instructions.some((mockedInstruction)=>{
return !(_optionalChain$7([transaction, 'optionalAccess', _8 => _8.message, 'optionalAccess', _9 => _9.compiledInstructions])).some((instruction)=>{
let instructionProgramId = transaction.message.staticAccountKeys[instruction.programIdIndex].toString();
if(normalize(instructionProgramId) != normalize(mockedInstruction.to)) { return false }
if(!mockedInstruction.params && !mockedInstruction.keys) { return true }
return mockInstructionsMatch(mockedInstruction, instruction) && mockKeysMatch(mockedInstruction, instruction, transaction)
})
}))
)
};
let mockHasWrongBalanceData = (mock, type, params) => {
return mock[type].for && normalize(params) !== normalize(mock[type].for)
};
let mockHasWrongToAddress = (mock, type, params) => {
if(mock[type].to == undefined) { return false }
return normalize(mock[type].to) !== normalize(params[0])
};
let mockHasWrongBlock = (mock, block) => {
if((typeof block == 'undefined' || block == 'latest') && typeof mock.block == 'undefined'){ return false }
if(typeof mock.block == 'undefined') { return true }
return ethers.ethers.utils.hexValue(mock.block) != block
};
let mockHasWrongParams = (mock, type, params, provider) => {
if(mock.request == undefined) { return false }
if(mock.request.params == undefined) { return false }
if(params == undefined) { return true }
let requestParams;
if(params && params[1]) {
requestParams = JSON.parse(JSON.stringify(params[1]));
delete requestParams.encoding;
} else {
requestParams = params;
}
if(JSON.stringify(requestParams) != JSON.stringify(mock.request.params)) {
return true
}
};
let mockHasWrongNetworkAction = (mock, type, params) => {
if(type != 'network') { return false }
return Object.keys(mock.network)[0] != Object.keys(params)[0]
};
let findMock = ({ type, blockchain, params, method, block, provider }) => {
return mocks.find((mock) => {
if (mockIsNotAnObject(mock)) {
return
}
if (mockHasWrongBlockchain(mock, blockchain)) {
return
}
if (mockHasWrongProvider(mock, provider)) {
return
}
if (mockHasWrongType(mock, type)) {
return
}
if (mockHasWrongMethod(mock, method)) {
return
}
if (mockHasWrongTransactionData(mock, type, params)) {
return
}
if (mockHasWrongTransactionInstructions(mock, type, params)) {
return
}
if (mockHasWrongBalanceData(mock, type, params)) {
return
}
if (mockHasWrongToAddress(mock, type, params)) {
return
}
if (mockHasWrongParams(mock, type, params)) {
return
}
if (mockHasWrongBlock(mock, block)) {
return
}
if (mockHasWrongNetworkAction(mock, type, params)) {
return
}
return mock
})
};
let findAnyMockForThisAddress = ({ type, params }) => {
return mocks.find((mock) => {
if (normalize(_optionalChain$7([mock, 'access', _10 => _10[type], 'optionalAccess', _11 => _11.to])) !== normalize(params[0])) {
return
}
return mock
})
};
let findMockByTransactionHash = (hash) => {
return mocks.find((mock) => {
return _optionalChain$7([mock, 'optionalAccess', _12 => _12.transaction, 'optionalAccess', _13 => _13._id]) == hash && (
_optionalChain$7([mock, 'optionalAccess', _14 => _14.transaction, 'optionalAccess', _15 => _15._confirmed]) || _optionalChain$7([mock, 'optionalAccess', _16 => _16.transaction, 'optionalAccess', _17 => _17._failed])
)
})
};
let requestAccounts = ({ mock })=> {
mock.calls.add({});
if (mock.accounts.return instanceof Error) {
return Promise.reject(mock.accounts.return)
} else {
return Promise.resolve(
mock.accounts.return
)
}
};
let connect = function ({ blockchain, provider }) {
let mock = findMock({ type: 'accounts', blockchain, provider });
if (mock) {
if(mock.accounts.delay) {
return new Promise((resolve)=>{
setTimeout(()=>{
requestAccounts({ mock }).then((accounts)=>{ resolve({ publicKey: new solanaWeb3_js.PublicKey(accounts[0]) }); });
}, mock.accounts.delay);
})
} else {
return requestAccounts({ mock }).then((accounts)=>{ return { publicKey: new solanaWeb3_js.PublicKey(accounts[0]) } })
}
} else {
raise(
'Web3Mock: Please mock accounts: ' +
JSON.stringify({
blockchain,
accounts: {
return: ['YOUR ACCOUNT HERE']
}
})
);
}
};
const getLatestBlockhash = ({ blockchain })=>{
return({
blockhash: getRandomTransactionHash(blockchain),
lastValidBlockHeight: getCurrentBlock()
})
};
let events$2 = {};
let triggerEvent$2 = (eventName, value) => {
if(events$2[eventName] == undefined) { return }
events$2[eventName].forEach(function (callback) {
callback(value);
});
};
let on$2 = (eventName, callback) => {
if (events$2[eventName] === undefined) {
events$2[eventName] = [];
}
events$2[eventName].push(callback);
};
let removeListener$1 = (eventName, callback) => {
if (events$2[eventName]) {
let index = events$2[eventName].indexOf(callback);
if (index >= 0) {
events$2[eventName].splice(index, 1);
}
}
};
function _optionalChain$6(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let balance = function ({ blockchain, params, provider }) {
let mock = findMock({ blockchain, type: 'balance', params, provider });
if (mock && _optionalChain$6([mock, 'access', _ => _.balance, 'optionalAccess', _2 => _2.return]) != undefined) {
mock.calls.add(params);
if (_optionalChain$6([mock, 'optionalAccess', _3 => _3.balance, 'optionalAccess', _4 => _4.return]) instanceof Error) {
return Promise.reject(mock.balance.return)
} else {
return Promise.resolve(mock.balance.return)
}
} else {
raise(
'Web3Mock: Please mock the balance request: ' +
JSON.stringify({
blockchain: blockchain,
balance: {
for: params,
return: 'PUT BALANCE AMOUNT HERE',
},
})
);
}
};
const NATIVE = Blockchains__default['default'].findByName('solana').currency.address;
let marshalValue = (value, blockchain)=>{
if(typeof value == 'number') {
return value
} else if (typeof value == 'string' && value == NATIVE) {
return new solanaWeb3_js.PublicKey(value)
} else if (typeof value == 'string' && value.match(/[^0-9-]/)) {
try {
return new solanaWeb3_js.PublicKey(value)
} catch(e) { // normal string
return solanaWeb3_js.Buffer.from(value, 'utf-8')
}
} else if (typeof value == 'string' && !value.match(/[^0-9-]/)) {
return new solanaWeb3_js.BN(value, 10)
} else if (typeof value == 'boolean') {
return value
} else if (value instanceof solanaWeb3_js.Buffer) {
return value
} else if (value instanceof Array) {
return value.map((value)=>marshalValue(value))
} else if (value instanceof Object) {
let valueObject = {};
Object.keys(value).forEach((key)=>{
let singleValue = value[key];
valueObject[key] = marshalValue(singleValue);
});
return valueObject
} else if (value === null) {
return null
} else {
raise(`Web3Mock: Unknown value type ${value}`);
}
};
let callMock = ({ blockchain, mock, params, provider, raw })=> {
mock.calls.add(params);
if (mock.request.return instanceof Error) {
return Promise.reject(mock.request.return.message)
} else if(raw) {
return Promise.resolve(mock.request.return)
} else if(!mock.request.return) {
return Promise.resolve(mock.request.return)
} else if(mock.request.return && mock.request.return.raw ) {
return Promise.resolve(mock.request.return.raw)
} else {
let response = marshalValue(mock.request.return);
if(mock.request.api) {
let size;
if(mock.request.responseSize) {
size = mock.request.responseSize;
} else if(mock.request.api.span > 0) {
size = mock.request.api.span;
} else {
size = 1000;
}
let buffer = solanaWeb3_js.Buffer.alloc(size);
mock.request.api.encode(response, buffer);
return Promise.resolve(
[buffer.toString('base64'), 'base64']
)
} else {
return Promise.resolve(response)
}
}
};
let responseData = function ({ blockchain, provider, method, params, raw }) {
let mock = findMock({ blockchain, type: 'request', params, method, provider });
if(mock) {
if(mock.request.delay) {
return new Promise((resolve)=>{
setTimeout(()=>resolve(callMock({ blockchain, mock, params, provider, raw })), mock.request.delay);
})
} else {
return callMock({ blockchain, mock, params, provider, raw })
}
} else {
mock = findAnyMockForThisAddress({ type: 'request', params });
if (mock) {
raise(
'Web3Mock: Please mock the request: ' +
JSON.stringify({
blockchain,
request: getRequestToBeMocked({ mock, method, params, provider }),
})
);
} else {
raise('Web3Mock: Please mock the request to: ' + params[0]);
}
}
};
let getRequestToBeMocked = ({ mock, params, method, provider }) => {
let address = params[0];
mock.request.api;
let toBeMocked = {
to: address,
method: method,
return: 'Your Value',
};
if(mock.api){
toBeMocked.api = ['PLACE API HERE'];
}
if(params[1]) {
let requestParams = JSON.parse(JSON.stringify(params[1]));
delete requestParams.encoding;
toBeMocked.params = requestParams;
}
return toBeMocked
};
let request$1 = ({ blockchain, provider, method, params }) => {
switch (method) {
case 'getBalance':
return balance({ blockchain, params: params[0], provider }).then((value)=>{
return {
jsonrpc: '2.0',
id: '1',
result: {
context:{ apiVersion: '1.10.26', slot: 140152926 },
value
}
}
})
case 'getBlockHeight':
return {
jsonrpc: '2.0',
id: '1',
result: getCurrentBlock()
}
case 'getSlot':
return {
jsonrpc: '2.0',
id: '1',
result: getCurrentBlock()
}
case 'getMinimumBalanceForRentExemption':
return responseData({ blockchain, provider, method, params })
.then((data)=>{
return({
jsonrpc: '2.0',
id: '1',
result: data
})
})
case 'getAccountInfo':
return responseData({ blockchain, provider, method, params })
.then((data)=>{
let value;
if(data) {
value = {
data,
executable: false,
owner: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
lamports: 3361680,
rentEpoch: 326
};
} else {
value = data;
}
return({
jsonrpc: '2.0',
id: '1',
result: {
context:{ apiVersion: '1.10.26', slot: 140152926 },
value
}
})
})
case 'getProgramAccounts':
return responseData({ blockchain, provider, method, params })
.then((data)=>{
return({
jsonrpc: '2.0',
id: '1',
result: data
})
})
case 'getTokenAccountBalance':
return responseData({ blockchain, provider, method, params, raw: true })
.then((value)=>{
return({
jsonrpc: '2.0',
id: '1',
result: {
context:{ apiVersion: '1.10.26', slot: 140152926 },
value
}
})
})
case 'getSignaturesForAddress':
return responseData({ blockchain, provider, method, params, raw: true })
.then((value)=>{
return({
jsonrpc: '2.0',
id: '1',
result: value
})
})
default:
raise('Web3Mock request: Unknown request method ' + method + '!');
}
};
let request = ({ blockchain, request, provider }) => {
switch (request.method) {
default:
raise('Web3Mock request: Unknown request method ' + request.method + '!');
}
};
let setCurrentNetwork = (network)=>{
};
function _optionalChain$5(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let sign = function ({ blockchain, params, provider }) {
let mock = findMock({ blockchain, type: 'signature', params, provider });
if (mock && _optionalChain$5([mock, 'access', _ => _.signature, 'optionalAccess', _2 => _2.return])) {
mock.calls.add(params);
if(mock.signature.delay) {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
if (mock.signature.return instanceof Error) {
reject(mock.signature.return);
} else {
resolve(mock.signature.return);
}
}, mock.signature.delay);
})
} else {
if (mock.signature.return instanceof Error) {
return Promise.reject(mock.signature.return)
} else {
return Promise.resolve(mock.signature.return)
}
}
} else {
raise(
'Web3Mock: Please mock the sign request: ' +
JSON.stringify({
blockchain: blockchain,
signature: {
params: params,
return: 'PUT SIGNATURE HERE',
},
})
);
}
};
function _optionalChain$4(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let signAndSendTransaction = ({ blockchain, params, provider }) => {
let mock = findMock({ type: 'transaction', params, provider });
if(mock) {
mock.calls.add(params);
const publicKey = params.message.staticAccountKeys[0].toString();
if(mock.transaction.delay) {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
if (mock.transaction.return instanceof Error) {
reject(mock.transaction.return);
} else {
resolve({
publicKey,
signature: mock.transaction._id
});
}
}, mock.transaction.delay);
})
} else {
if (mock.transaction.return instanceof Error) {
return Promise.reject(mock.transaction.return)
} else {
return Promise.resolve({
publicKey,
signature: mock.transaction._id
})
}
}
} else {
raise(
'Web3Mock: Please mock the following transaction: ' +
JSON.stringify({
blockchain,
transaction: getTransactionToBeMocked(params),
})
);
}
};
let getTransactionToBeMocked = (transaction) =>{
let from = _optionalChain$4([transaction, 'optionalAccess', _ => _.message, 'optionalAccess', _2 => _2.staticAccountKeys, 'optionalAccess', _3 => _3.length]) ? transaction.message.staticAccountKeys[0].toString() : 'FROM';
return {
from,
instructions: (_optionalChain$4([transaction, 'optionalAccess', _4 => _4.message, 'optionalAccess', _5 => _5.compiledInstructions]) || []).map((instruction)=>{
let to = _optionalChain$4([transaction, 'optionalAccess', _6 => _6.message, 'optionalAccess', _7 => _7.staticAccountKeys, 'optionalAccess', _8 => _8.length]) ? transaction.message.staticAccountKeys[instruction.programIdIndex].toString() : 'TO';
return {
to,
api: ["API HERE"],
params: { value: "HERE" }
}
})
}
};
let getSignatureStatus = ({ signature }) => {
let mock = findMockByTransactionHash(signature);
if(mock && mock.transaction._confirmedAtBlock) {
const confirmations = getCurrentBlock()-mock.transaction._confirmedAtBlock-1;
return({
context: {apiVersion: '1.10.31', slot: 143064206},
value: {
confirmationStatus: confirmations == 0 ? "confirmed" : "finalized",
confirmations,
err: mock.transaction._failed ? { InstructionError: [0, 'Error'] } : null,
slot: 143062809,
status: mock.transaction._failed ? { Err: { InstructionError: [0, 'Error'] } } : { Ok: null }
}
})
} else {
return({
context: {apiVersion: '1.10.31', slot: 143064206},
value: null
})
}
};
let getConfirmedTransaction = ({ signature }) => {
let mock = findMockByTransactionHash(signature);
if(mock && mock.transaction._confirmedAtBlock) {
getCurrentBlock()-mock.transaction._confirmedAtBlock-1;
return({
blockTime: 1658913018,
slot: 143351809,
transaction: {
signatures: [mock.transaction._id],
message: {
compiledInstructions: mock.transaction.compiledInstructions ? mock.transaction.compiledInstructions : []
}
},
meta: {
err: mock.transaction._failed ? { InstructionError: [0, 'Error'] } : null,
logMessages: mock.transaction._failedReason ? [mock.transaction._failedReason] : (mock.transaction.logMessages || [])
}
})
} else {
return(null)
}
};
function _optionalChain$3(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let simulateTransaction = ({ blockchain, params, provider }) => {
let mock = findMock({ type: 'simulate', params, provider });
if(!mock) {
let from = _optionalChain$3([params, 'optionalAccess', _ => _.message, 'optionalAccess', _2 => _2.staticAccountKeys, 'optionalAccess', _3 => _3.length]) ? params.message.staticAccountKeys[0].toString() : 'FROM';
raise(
'Web3Mock: Please mock the simulation: ' +
JSON.stringify({
blockchain,
simulate: {
from,
instructions: (_optionalChain$3([params, 'optionalAccess', _4 => _4.message, 'optionalAccess', _5 => _5.compiledInstructions]) || []).map((instruction)=>{
let to = _optionalChain$3([params, 'optionalAccess', _6 => _6.message, 'optionalAccess', _7 => _7.staticAccountKeys, 'optionalAccess', _8 => _8.length]) ? params.message.staticAccountKeys[instruction.programIdIndex].toString() : 'TO';
return {
to,
api: 'API HERE'
}
}),
return: "YOUR RETURN HERE"
}
})
);
} else {
return({ value: mock.simulate.return })
}
};
let mock$3 = ({ blockchain, configuration, window, provider }) => {
if(provider) {
provider.on = on$2;
provider.removeListener = removeListener$1;
provider._rpcRequest = (method, params)=>{
return request$1({ blockchain, provider, method, params })
};
provider.getLatestBlockhash = ()=>getLatestBlockhash({ blockchain });
provider.signAndSendTransaction = async (transaction)=>signAndSendTransaction({ blockchain, params: transaction, provider });
provider.simulateTransaction = async (transaction)=>simulateTransaction({ blockchain, params: transaction, provider });
provider.getSignatureStatus = async (signature)=>getSignatureStatus({ blockchain, signature, provider });
provider.getConfirmedTransaction = async (signature, params)=>getConfirmedTransaction({ blockchain, signature, params, provider });
provider.getTransaction = async (signature, params)=>getConfirmedTransaction({ blockchain, signature, params, provider });
}
window._solana = {
...window.solana,
connect: ()=>{
return connect({
blockchain, provider
})
},
on: on$2,
removeListener: removeListener$1,
request: (payload) => {
return request({
request: payload,
})
},
getLatestBlockhash: ()=>getLatestBlockhash({ blockchain }),
signAndSendTransaction: async (transaction)=>signAndSendTransaction({ blockchain, params: transaction, provider }),
getSignatureStatus: async (signature)=>getSignatureStatus({ blockchain, signature, provider }),
simulateTransaction: async (transaction)=>simulateTransaction({ blockchain, params: transaction, provider }),
getConfirmedTransaction: async (signature, params)=>getConfirmedTransaction({ blockchain, signature, params, provider }),
getTransaction: async (signature, params)=>getConfirmedTransaction({ blockchain, signature, params, provider }),
signMessage: (message)=>sign({ blockchain, params: [message], provider }).then((signature)=>{ return { signature } }),
};
return configuration
};
let events$1 = {};
let triggerEvent$1 = (eventName, values) => {
if(events$1[eventName] == undefined) { return }
events$1[eventName].forEach(function (callback) {
callback.apply(null, values);
});
};
let on$1 = (eventName, callback) => {
if (events$1[eventName] === undefined) {
events$1[eventName] = [];
}
events$1[eventName].push(callback);
};
let off = (eventName) => {
if (events$1[eventName]) {
events$1[eventName] = [];
}
};
function _optionalChain$2(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let mock$2 = ({ configuration, window }) => {
if(typeof _optionalChain$2([configuration, 'optionalAccess', _ => _.connector]) == 'undefined') { throw('You need to pass a WalletConnect connector instance when mocking WalletConnect!') }
if(configuration.connector.instance){ return configuration.connector.instance }
setWalletConnectClass(configuration.connector);
let instance = configuration.connector.instance = new configuration.connector();
instance.createSession = function(){ };
instance.sendCustomRequest = async function(options){
return await window._ethereum.request(options)
};
instance.connect = async function(){
let accounts = await window._ethereum.request({ method: 'eth_accounts' });
let chainId = await window._ethereum.request({ method: 'net_version' });
return {
accounts,
chainId
}
};
instance.on = on$1;
instance.off = off;
instance.sendTransaction = async function(transaction){
return await window._ethereum.request({ method: 'eth_sendTransaction', params: [transaction] })
};
instance.signPersonalMessage = async function(params){
return await window._ethereum.request({ method: 'eth_sign', params: [params[1], params[0]] })
};
};
let events = {};
let triggerEvent = (eventName, value) => {
if(events[eventName] == undefined) { return }
events[eventName].forEach(function (callback) {
callback(value);
});
};
let on = (eventName, callback) => {
if (events[eventName] === undefined) {
events[eventName] = [];
}
events[eventName].push(callback);
};
let removeListener = (eventName, callback) => {
if (events[eventName]) {
let index = events[eventName].indexOf(callback);
if (index >= 0) {
events[eventName].splice(index, 1);
}
}
};
function _optionalChain$1(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let mock$1 = ({ configuration, window }) => {
if(typeof _optionalChain$1([configuration, 'optionalAccess', _ => _.connector]) == 'undefined') { throw('You need to pass a WalletLink connector instance when mocking WalletLink!') }
if(configuration.connector.instance){ return configuration.connector.instance }
setWalletLinkClass(configuration.connector);
let instance = configuration.connector.instance = new configuration.connector();
instance.enable = async function(){
let accounts = await window._ethereum.request({ method: 'eth_accounts' });
return accounts
};
instance._relayProvider = async function() {
return {
setConnectDisabled: ()=>{}
}
};
instance.getChainId = async function() {
const blockchain = Blockchains__default['default'].findById(await window._ethereum.request({ method: 'eth_chainId' }));
return blockchain.networkId
};
instance.request = window._ethereum.request;
instance.on = on;
instance.removeListener = removeListener;
};
function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
let getBlockchain = (configuration) => {
if (typeof configuration === 'string') {
return configuration
} else if (typeof configuration === 'object' && !Array.isArray(configuration)) {
return configuration.blockchain
} else {
raise('Web3Mock: Unknown mock configuration type!');
}
};
let apiIsMissing = (type, configuration) => {
if(supported.evm.includes(configuration.blockchain)) {
if (
typeof configuration[type] == 'undefined' ||
typeof configuration[type].method == 'undefined'
) {
return false
}
return configuration[type] && _optionalChain([configuration, 'access', _ => _[type], 'optionalAccess', _2 => _2.api]) === undefined
} else if (supported.svm.includes(configuration.blockchain)) {
if(type == 'transaction') {
return _optionalChain([configuration, 'access', _3 => _3.transaction, 'optionalAccess', _4 => _4.instructions, 'optionalAccess', _5 => _5.every, 'call', _6 => _6((instruction)=>!instruction.api)])
} else if(type == 'simulate') {
return _optionalChain([configuration, 'access', _7 => _7.simulate, 'optionalAccess', _8 => _8.instructions, 'optionalAccess', _9 => _9.every, 'call', _10 => _10((instruction)=>!instruction.api)])
} else {
return false
}
}
};
let apiMissingErrorText = (type, configuration) => {
let configurationDuplicate = configuration;
if(configuration.provider) { configurationDuplicate.provider = "PROVIDER"; }
let suggestedConfiguration;
if(supported.evm.includes(configuration.blockchain)) {
suggestedConfiguration = Object.assign(configurationDuplicate, {
[type]: Object.assign(configurationDuplicate[type], { api: ['PLACE API HERE'] }),
});
} else if (supported.svm.includes(configuration.blockchain)) {
suggestedConfiguration = configurationDuplicate;
if(type == 'transaction') {
suggestedConfiguration.transaction.instructions = suggestedConfiguration.transaction.instructions.map((instruction)=>Object.assign(instruction, { api: 'PLACE API HERE' }));
} else if(type == 'simulate'){
suggestedConfiguration.simulate.instructions = suggestedConfiguration.simulate.instructions.map((instruction)=>Object.assign(instruction, { api: 'PLACE API HERE' }));
}
}
return (
'Web3Mock: Please provide the api for the ' +
type +
': ' +
JSON.stringify(suggestedConfiguration)
)
};
let preflight = (configuration) => {
if (configuration === undefined || configuration.length === 0) {
raise('Web3Mock: No mock defined!');
} else if (typeof configuration === 'object' && Object.keys(configuration).length === 0) {
raise('Web3Mock: Mock configuration is empty!');
} else if (typeof configuration != 'string' && typeof configuration != 'object') {
raise('Web3Mock: Unknown mock configuration type!');
}
if (apiIsMissing('request', configuration)) {
raise(apiMissingErrorText('request', configuration));
} else if (apiIsMissing('transaction', configuration)) {
raise(apiMissingErrorText('transaction', configuration));
} else if (apiIsMissing('simulate', configuration)) {
raise(apiMissingErrorText('simulate', configuration));
} else if (apiIsMissing('estimate', configuration)) {
raise(apiMissingErrorText('estimate', configuration));
}
};
let spy = (mock) => {
if (typeof mock != 'object') {
return mock
}
let spy = ()=>{};
if(mock) { Object.keys(mock).forEach((key)=>{ spy[key] = mock[key]; }); }
let calls = [];
spy.callCount = 0;
mock.calls = spy.calls = {
add: (call) => {
spy.callCount++;
calls.push(call);
},
all: () => calls,
count: () => calls.length,
};
spy.getCalls = (a)=>{ return calls };
spy.getCall = ()=>{ return calls[calls.length-1] };
spy.calledWithExactly = ()=>{};
spy.printf = (string)=> {
string = string.replace("%n", "Web3Mock");
string = string.replace("%C", calls.map((call)=>{return JSON.stringify(call)}).join("\n"));
return string
};
spy.called = ()=> { return calls.length > 1 };
spy.calledOnce = ()=> { return calls.length == 1 };
return spy
};
let mockWallet = ({ blockchain, configuration, window }) => {
let wallet = configuration.wallet;
switch (wallet) {
case 'metamask':
window.ethereum = window._ethereum;
window.ethereum.isMetaMask = true;
break
case 'coinbase':
window.ethereum = window._ethereum;
window.ethereum.isCoinbaseWallet = true;
window.ethereum.isWalletLink = true;
break
case 'phantom':
window.solana = window._solana;
window.solana.isPhantom = true;
window.phantom = window.solana;
break
case 'walletconnect':
mock$2({ configuration, window });
break
case 'walletlink':
mock$1({ configuration, window });
break
case false:
break
default:
if(supported.evm.includes(blockchain)) {
window.ethereum = window._ethereum;