Solana SplToken web3 : How can i create address/account owned by other address/account? - web3js

I would like to create other address/accounts belonging to my initial account, the goal is to have several separate addresses and carry out transactions by paying the fees from my main accounts.
It's like the exchanges create accounts that belong to them and they make transactions between by paying the fees.
This is my example:
// BANK or Exchange
const BankaccountKeypair = web3.Keypair.fromSecretKey([160,15,25, ...]);
const BANK_wallet = splEasy.Wallet.fromKeypair(connection,BankaccountKeypair);
// Customer A (to)
const A_wallet = splEasy.Wallet.fromKeypair(connection,web3.Keypair.fromSecretKey([20,18,125, ...]));
var myToken = new splToken.Token(
connection,
new web3.PublicKey('TRmbtbEW4g.......'),
splToken.TOKEN_PROGRAM_ID,
BANK_wallet
);
// A account (to)
var A_walletAccount = await myToken.getOrCreateAssociatedAccountInfo( A_wallet.publicKey );
// B account(from)
const B_walletAccount = await myToken.createAssociatedTokenAccount( BANK_wallet.publicKey );
// transaction
var transaction = new web3.Transaction()
.add(
splToken.Token.createTransferInstruction(
splToken.TOKEN_PROGRAM_ID,
B_walletAccount.address,
A_walletAccount.address,
BANK_wallet.publicKey,
[],
0
)
);
// signature
var signature = await web3.sendAndConfirmTransaction() ....
But I got an error on:
// B account(from)
const B_walletAccount = await myToken.createAssociatedTokenAccount( BANK_wallet.publicKey );
throw new TypeError('unexpected type, use Uint8Array');
^
TypeError: unexpected type, use Uint8Array
I tried by
const B_walletAccount = await myToken.createAssociatedTokenAccount([160,15,25, ...]);
But I got:
if (!allowOwnerOffCurve && !web3_js.PublicKey.isOnCurve(owner.toBuffer())) {
^
TypeError: owner.toBuffer is not a function
When I use
getOrCreateAssociatedAccountInfo(B_wallet);
it's working but, Transaction is failed :
var transaction = new web3.Transaction()
.add(
splToken.Token.createTransferInstruction(
splToken.TOKEN_PROGRAM_ID,
B_walletAccount1.address,
A_walletAccount.address,
BANK_wallet.publicKey,
[],
2000000
)
);
// error :
Transaction simulation failed: Error processing Instruction 0: custom program error: 0x4
Program TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA invoke [1]
Program log: Instruction: Transfer
Program log: Error: owner does not match
*/
I need to have lot of address without SOL/lamports that I should transfer myToken between those addresses

Related

Sending SPL tokens on solana network

I am using solana web3.js to send SOL tokens. I am using below code to send SOL tokens to other address:
import * as web3 from '#solana/web3.js';
// ...
// later
const sendToAddress = async(param) => {
const connection = new web3.Connection(web3.clusterApiUrl('devnet'));
let accountFromSecret = web3.Keypair.fromSecretKey(param.privateKey);
let base58ToSend = new web3.PublicKey(param.toAddress);
var transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: accountFromSecret.publicKey,
toPubkey: base58ToSend,
lamports: Number(param.amount), // number of SOL to send
}),
);
var signature = await web3.sendAndConfirmTransaction(connection, transaction, [
accountFromSecret,
]);
}
With this I am able to successfully send SOL.
But I also want to send other SPL tokens like Raydium (RAY), Star Atlas (ATLAS), ORBS. How do I send these SPL tokens?

Send Token erc20 usign Web3.js( Private Key. Account unloked. SignTransaction )

If send to Avax but not my Erc20 Token. Thank you for your help
First we get the url of the rcp.
Then we create an instance of web3.js.
Then with our private key you create an account.
We create an instance of our contract by passing it the abi and the address of the contract as parameters.
We estimate the gas with estimateGas passing it an object that indicates the function of the abi that is going to be used, the address of the contract, to whom it is going to be sent.
We create a transfer object
We obtain the balance to know the initial balance
We sign the transaction with our private key
We send the transaction
We get the bottom line
My code
`
const transferToeknErc20 = async () => {
const amount = '1000000000000000';
const jsonInterface = [{"inputs":[],"stateMutability":....
const contractAddress = '0x7B9...';
const privateKeyWallet = '14f...';
const chainId = 43113;
const address_to = '0x86...';
//NODE
const NODE_URL = "https://api.avax-test.network/ext/bc/C/rpc";
//WEB3
const web3Global = new Web3( new Web3.providers.HttpProvider(NODE_URL));
//Creamos una cuenta con la llave privada
const account = web3Global.eth.accounts.privateKeyToAccount(privateKeyWallet);
//CONTRACT
const contract = new web3Global.eth.Contract(jsonInterface, contractAddress);
//////////////////////////////////////////////////////////////////////////////
let estimateGas = await web3Global.eth.estimateGas({
value: '0x0', // Only tokens
data: contract.methods.transfer(address_to, amount).encodeABI(),
from: account.address,
to: address_to
});
//////////////////////////////////////////////////////////////////////////////
const transactionObject = {
value:'0x0',
data:contract.methods.transfer(address_to, amount).encodeABI(),
from: account.address,
to: address_to,
gas:web3Global.utils.toHex(Math.round(estimateGas * 1.10)),
gasLimit:web3Global.utils.toHex(Math.round(estimateGas * 1.10)),
chainId,
}
//get balanace
let balance = await contract.methods.balanceOf(account.address).call();
console.log('balance init', balance)
//Sing
const signText = await web3Global.eth.accounts.signTransaction(transactionObject, privateKeyWallet);
//Send Transaction
const reciep = await web3Global.eth.sendSignedTransaction(signText.rawTransaction);
//get balanace
balance = await contract.methods.balanceOf(account.address).call();
console.log('balance end', balance)
return null;
///////////////////////////////////////////////////////////////////////////////////////
}
`

TypeError: this is undefined in rect js while passing BigNumber in solana RPC Request

i am getting this is undefined at BN while making RPC request to a function in solana smart contract
'''
let token1Amount = BN(token1_amount);
let token2Amount = BN(token2_amount)
const add_liquidity = await router_program.rpc.addLiquidity(
token1Amount,
token2Amount,
{
accounts: {
// poolAccount: pool_Account.publicKey, //account which stores the individual pair data
userToken1Account: usetoken1_account,
userToken2Account: usetoken2_account,
poolToken1Account: new PublicKey(tokenaccount_1),
poolToken2Account: new PublicKey(tokenaccount_2),
owner: provider.wallet.publicKey,
tokenProgram: TOKEN_PROGRAM_ID,
// systemProgram : SystemProgram.programId ,
// associatedTokenProgram: spl.ASSOCIATED_TOKEN_PROGRAM_ID,
// rent: anchor.web3.SYSVAR_RENT_PUBKEY,
tokensProgram: TOKEN_ID,
// poolProgram: pair.programId,
// pairAccount: pairAccount.publicKey
},
// signers: [provider]
}
);
'''
This is a shot in the dark, but I think you need new so that your BNs have a this context, so instead try:
let token1Amount = new BN(token1_amount);
let token2Amount = new BN(token2_amount);

How to get a reference to a former created Token in Solana (client side, JS)

I'm able to create a token and mint it into an spl account address.
But when I restart my program, how do I get a reference to that Token, so that I mint again?
const web3 = require("#solana/web3.js");
const splToken = require('#solana/spl-token');
const { PublicKey, Keypair, Transaction, SystemProgram, LAMPORTS_PER_SOL, sendAndConfirmTransaction, clusterApiUrl } = require("#solana/web3.js");
let secretKey = Uint8Array.from([233, 65, 11, rest of my secret]);
let fromWindowsWallet = Keypair.fromSecretKey(secretKey);
let connection = new web3.Connection(clusterApiUrl('devnet'));
(async () => {
//create my new token mint
let SWAB = await splToken.Token.createMint(
connection,
fromWindowsWallet,
fromWindowsWallet.publicKey,
fromWindowsWallet.publicKey,
2,
splToken.TOKEN_PROGRAM_ID,
);
console.log(SWAB.publicKey) // -> PublicKey {
_bn: <BN: 2643549b60882496a15407c2f1a6139dd2c4128879480b1d56fdd464550db22b>
}
// ... continue with that Token SWAB
}
So when I restart my program, how can I get a reference to the Token SWAB again? I tried:
let pubKey = new PublicKey("<BN: 6ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a9>");
let SWAB = new splToken.Token(
connection,
pubKey,
splToken.TOKEN_PROGRAM_ID,
fromWindowsWallet
)
but that throws: Error: Non-base58 character
After creating the Token I can get the pubKey with:
console.log(SWAB.publicKey.toBase58()) // 3aN3KP6kQdBvTHTeK785Uuykddram97B844RoJc19VNS
Then I can get a reference to the Token like this and continue minting:
let pubKey = new PublicKey('3aN3KP6kQdBvTHTeK785Uuykddram97B844RoJc19VNS');
let SWAB = new splToken.Token(
connection,
pubKey,
splToken.TOKEN_PROGRAM_ID,
fromWindowsWallet
)
(connection and fromWindowsWallet are defined in the code of my question)

Get total amount of tokens received from a specific address using Web3.js

in a scenario, WalletA is receiving TokenB in a regular basis from AddressC.
AddressC only sends TokenB, nothing else.
in etherscan or bscscan it is simple to see how much of TokenB is received in WalletA and "from" field is there so you can do some math to get total.
How can this be done using web3? I couldn't find any relevant api call in web3 documents.
I can get total balance of TokenB in WalletA by web3.js but I need the count of tokens only sent from AddressC.
Thanks.
As per the ERC-20 standard, each token transfer emits a Transfer() event log, containing the sender address, receiver address and token amount.
You can get the past event logs using the web3js general method web3.eth.getPastLogs(), encode the inputs and decode the outputs.
Or you can supply ABI JSON of the contract (it's enough to use just the Transfer() event definition in this case) and use the web3js method web3.eth.Contract.getPastEvents(), which encodes the inputs and decodes the outputs for you based on the provided ABI JSON.
const Web3 = require('web3');
const web3 = new Web3('<provider_url>');
const walletA = '0x3cd751e6b0078be393132286c442345e5dc49699'; // sender
const tokenB = '0xdAC17F958D2ee523a2206206994597C13D831ec7'; // token contract address
const addressC = '0xd5895011F887A842289E47F3b5491954aC7ce0DF'; // receiver
// just the Transfer() event definition is sufficient in this case
const abiJson = [{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"}];
const contract = new web3.eth.Contract(abiJson, tokenB);
const fromBlock = 10000000;
const toBlock = 13453500;
const blockCountIteration = 5000;
const run = async () => {
let totalTokensTranferred = 0;
for (let i = fromBlock; i <= (toBlock - blockCountIteration); i += blockCountIteration) {
//console.log("Requesting from block", i, "to block ", i + blockCountIteration - 1);
const pastEvents = await contract.getPastEvents('Transfer', {
'filter': {
'from': walletA,
'to': addressC,
},
'fromBlock': i,
'toBlock': i + blockCountIteration - 1,
});
}
for (let pastEvent of pastEvents) {
totalTokensTranferred += parseInt(pastEvent.returnValues.value);
}
console.log(totalTokensTranferred);
}
run();

Resources