Invoking recursively transfer function in Solana - rust

Im new to solana and I'm trying ot implement multisig wallet with transfer SOL functionallity. Basicly i followed implementation from this repo: https://github.com/coral-xyz/multisig.
The problem is when I try to invoke my transfer function:
pub fn transfer_funds( ctx:Context<Transfer>,amount:u64) -> Result<()> {
let amount_of_lamports = amount;
let from = ctx.accounts.from.to_account_info();
let to = ctx.accounts.to.to_account_info();
**from.try_borrow_mut_lamports()? -= amount_of_lamports;
**to.try_borrow_mut_lamports()? += amount_of_lamports;
Ok(())
}
From execute transaction function:
pub fn execute_transaction(ctx: Context<ExecuteTransaction>) -> Result<()> {
msg!("Executing Transaction");
if ctx.accounts.transaction.did_execute {
return Err(ErrorCode::AlreadyExecuted.into());
}
let sig_count = ctx
.accounts
.transaction
.signers
.iter()
.filter(|&did_sign| *did_sign)
.count() as u64;
if sig_count < ctx.accounts.wallet.threshold {
return Err(ErrorCode::NotEnoughSigners.into());
}
let mut ix: Instruction = (*ctx.accounts.transaction).deref().into();
ix.accounts = ix
.accounts
.iter()
.map(|acc| {
let mut acc = acc.clone();
if &acc.pubkey == ctx.accounts.wallet_signer.key {
acc.is_signer = true;
}
acc
})
.collect();
let wallet_key = ctx.accounts.wallet.key();
let seeds = &[wallet_key.as_ref(), &[ctx.accounts.wallet.nonce]];
let signer = &[&seeds[..]];
let accounts = ctx.remaining_accounts;
solana_program::program::invoke_signed(&ix, accounts, signer)?;
ctx.accounts.transaction.did_execute = true;
emit!(TransactionExecutedEvent {
wallet: ctx.accounts.wallet.key(),
transaction: ctx.accounts.transaction.key(),
});
Ok(())
}
}
I Get Error: Transaction simulation failed Error processing Instruction insufficient account keys for instruction
I can without problems execute set_owners and change_threshold functions.
My Transaction for transfer looks like this:
const [walletSigner] = await web3.PublicKey.findProgramAddress(
[new PublicKey(state.connection.msig).toBuffer()],
state.connection.program.programId
);
let data;
try {
data = state.connection.program.coder.instruction.encode(
'transfer_funds',
{
amount: new BN(args.amount),
}
);
} catch (err) {
console.log(err);
}
const accounts = [
{
pubkey:mustisigPublicKey,
isWritable: true,
isSigner: false,
},
{
pubkey: walletSigner,
isWritable: false,
isSigner: true,
},
];
const transaction = web3.Keypair.generate();
const tx = await state.connection.program.rpc.createTransferTransaction(
state.connection.program.programId,
accounts,
data,
{
accounts: {
wallet:mustisigPublicKey,
transaction: transaction.publicKey,
initiator: state.connection.provider.wallet.publicKey,
to: args.to,
from:mustisigPublicKey,
systemProgram: web3.SystemProgram.programId,
},
instructions: [
await state.connection.program.account.wallet.createInstruction(
transaction,
1000
),
],
signers: [transaction],
}
);`
I'm guessing that this is related somehow to accounts context not being forwarded to transfer function, but as I'm complete beginner I cant be sure :/

Related

How to speed up Fetching Google Place and Photos

I currently have the following code to fetch matching Google Places according to a received query as shown below:
async function searchGoogleBusiness(req, res) {
let { name } = req.query;
const apiKey = process.env.API_KEY;
const searchUrl = `https://maps.googleapis.com/maps/api/place/textsearch/json?query=`;
try {
let { data } = await axios.get(`${searchUrl}${name}&key=${apiKey}`)
let { status, error_message, results } = data;
if (status === 'OK') {
let businessResults = [];
if ((results ?? []).length > 0) {
for (let business of results) {
let businessDetails = {
....
}
if ((business.photos ?? []).length > 0) {
let { width = 1200, height = 1200, photo_reference } = business.photos[0];
let photoUrl = `https://maps.googleapis.com/maps/api/place/photo?photoreference=${photo_reference}&sensor=false&maxheight=${height}&maxwidth=${width}&key=${apiKey}`
try {
let businessPhotoResponse = await axios.get(photoUrl, { responseType: 'arraybuffer' });
let imageBuffer = businessPhotoResponse.data;
let base64Image = Buffer.from(imageBuffer, 'binary').toString('base64');
businessDetails.photo = `data:${businessPhotoResponse.headers['content-type']};base64,${base64Image}`;
} catch (e) {
businessDetails.photo = business.icon;
}
} else {
businessDetails.photo = business.icon;
}
businessResults.push(businessDetails);
}
}
...//Omitted
}
...//Omitted
} catch (e) {
...//Omitted
}
}
As you can immediately notice, the function takes forever to return when the results are more than 5 and the reason is because I'm looping through each business to make another api call to fetch each photo.
I don't like this approach at all.
This idea of making another network call using photoReferences is really affecting my site speed and basically just makes my users angry.
Is there no way to automatically fetch the photo urls along just in the first request?

My anchor test is not working in test.js, invalid argument error

When I am running an anchor test, I am getting the following error, of invalid arguments. Funnily enough, the crowdFundingPlatform argument it says is missing, is never in any of the code I wrote, as you can see below this error in my anchor files.
CrowdFunding
1) Is initialized!
0 passing (22ms)
1 failing
1) CrowdFunding
Is initialized!:
Error: Invalid arguments: crowdFundingPlatform not provided.
Here is the JS test:
describe("CrowdFunding", () => {
// Configure the client to use the local cluster.
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.CrowdFunding;
const platform = anchor.web3.Keypair.generate();
it('Is initialized!', async () => {
const crowd_funding_platform = anchor.web3.Keypair.generate();
await program.rpc.initialize(
"limk",
"description",
"title",
new anchor.BN(1),
{
accounts: {
crowd_funding_platform: crowd_funding_platform.publicKey,
authority: program.provider.wallet.publicKey,
system_program: anchor.web3.SystemProgram.programId,
},
signers: [crowd_funding_platform],
})
const PlatformAccount = await program.account.crowd_funding_platform.fetch(crowd_funding_platform.publicKey);
console.log(PlatformAccount);
});
})
Here is the smart contract framework for the initialize function, as you can see, there is no 'crowdFundingPlatform'
pub fn initialize(
ctx: Context<Initialize>,
Image: String,
Description: String,
Title: String,
Donation_Goal: u64,
) -> ProgramResult {
let campaign = &mut ctx.accounts.crowd_funding_platform;
campaign.Image = Image;
campaign.Description = Description;
campaign.Title = Title;
campaign.Amount_Donated = 0;
campaign.Donation_Goal = Donation_Goal;
Ok(())
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(
init,
payer = authority,
space = size_of::<CrowdFundingPlatform>() + 8,
seeds = [b"crowd_funding_platform".as_ref()],
bump
)]
pub crowd_funding_platform: Account<'info, CrowdFundingPlatform>,
#[account(mut)]
pub authority: Signer<'info>,
pub system_program: Program<'info, System>,
}
Replace crowd_funding_platform and system_program with crowdFundingPlatform and systemProgram in js file.
Here is full js code:
describe("CrowdFunding", () => {
// Configure the client to use the local cluster.
const provider = anchor.AnchorProvider.env();
anchor.setProvider(provider);
const program = anchor.workspace.CrowdFunding;
const platform = anchor.web3.Keypair.generate();
it('Is initialized!', async () => {
const [crowdFundingPlatform] = await anchor.web3.PublicKey.findProgramAddress([Buffer.from("crowd_funding_platform")], program.programId);
await program.methods.initialize(
"limk",
"description",
"title",
new anchor.BN(1)
)
.accounts({
crowdFundingPlatform,
authority: program.provider.wallet.publicKey,
systemProgram: anchor.web3.SystemProgram.programId,
})
.rpc();
const PlatformAccount = await program.account.crowdFundingPlatform.fetch(crowdFundingPlatform.publicKey);
console.log(PlatformAccount);
});
})

Messages are large, You may want to consider smaller messages. node-ipc and swift (OSX)

I have a node app that is trying to communicate with a swift application using a unix socket.
I am broadcasting a Message ever 3 seconds using the following code with node-ipc:
const ipc = require('node-ipc').default;
// Run IPC server for testing
const first = "FIRST";
const second = "SECOND";
const ipcSocketPath = `/tmp/${ipcAppId}`;
async function setupCoreCommunicationIpc() {
await new Promise((resolve) => {
ipc.serve(ipcSocketPath, () => {
ipc.server.on('ping', (data, socket) => {
ipc.server.emit(socket, 'pong');
});
return resolve(true);
});
ipc.server.start();
});
}
function sendMessage(message, payload = {}) {
ipc.server.broadcast(message, { ...payload, "valueOne": first, "valueTwo": seconds });
}
(async () => {
try {
await setupCoreCommunicationIpc()
} catch (e) {
// Deal with the fact the chain failed
}
// `text` is not available here
})();
setInterval(async () => {
await sendMessage("first:message", {core_id: ipcAppId, app_id: ipcAppId, message_id: 5})
}, 3000);
The code on swift is a bit more complicated. But I am able to connect to the unix socket and receive the message. The Problem is the sending of the AckMessage. I tried different approaches for sending the message but it would not work. Here is the code in swift:
func startSocketStack(valueOne: String, valueTwo: String){
let MTU = 65536
let path = "/tmp/\(valueTwo)"
print("starting socket at: %\(path)%")
let client = socket(AF_UNIX, SOCK_STREAM, 0)
var address = sockaddr_un()
//address.sun_family = UInt8(AF_UNIX)
address.sun_family = sa_family_t(AF_UNIX)
//address.sun_len = UInt8(MemoryLayout<sockaddr_un>.size)
address.sun_len = UInt8(MemoryLayout<UInt8>.size + MemoryLayout<sa_family_t>.size + path.utf8.count + 1)
strlcpy(&address.sun_path.0, path, MemoryLayout.size(ofValue: address.sun_path))
var adressUnwrap = address
withUnsafePointer(to: &adressUnwrap) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
let connection = connect(client, $0, socklen_t(address.sun_len))
if (connection != 0) {
print("startSocket: could not connect to socket at \(path)")
}
}
}
var buffer = UnsafeMutableRawPointer.allocate(byteCount: MTU,alignment: MemoryLayout<CChar>.size)
while(true) {
let readResult = read(client, &buffer, MTU)
if (readResult == 0) {
break; // end of file
} else if (readResult == -1) {
print("Error reading form client\(client) - \(errno)")
break; // error
} else {
let strResult = withUnsafePointer(to: &buffer) {
$0.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: readResult)) {
String(cString: $0)
}
}
print("Received form client(\(client)): §\(strResult)§")
print("§\(strResult)§")
let trimmedString = strResult.components(separatedBy: .whitespacesAndNewlines).joined()
print("§\(trimmedString)§")
struct Message: Decodable {
let type: String
let data: MessageData
struct MessageData: Decodable {
var valueOne: String
var valueTwo: String
var message_id: String
}
}
struct AckMessage: Encodable {
let type: String
let data: Bool
}
do {
let jsonMessage = trimmedString.components(separatedBy: "}")[0] + "}" + "}"
let jsonData = jsonMessage.trimmingCharacters(in: CharacterSet.newlines).data(using: .utf8)!
let receivedMessage: Message = try JSONDecoder().decode(Message.self, from: jsonData)
let messageId = receivedMessage.data.message_id
let ackMessage = AckMessage(type: messageId, data: true)
let jsonAckMessage = try JSONEncoder().encode(ackMessage)
let delimiter = #"\f"#.bytes
let jsonAckMessageWithDelimiter = jsonAckMessage + delimiter
print("jsonAckMessageWithDelimiter")
print(jsonAckMessageWithDelimiter)
// first attempt
do {
try jsonAckMessageWithDelimiter.withUnsafeBytes() { [unowned self] (buffer: UnsafeRawBufferPointer) throws -> Int in
let buffer = buffer.baseAddress!
print(buffer)
let bufSize = jsonAckMessageWithDelimiter.count
print(bufSize)
var sent = 0
var sendFlags: Int32 = 0
while sent < bufSize {
var s = 0
s = send(client, buffer.advanced(by: sent), Int(bufSize - sent), sendFlags)
if s <= 0 {
if errno == EAGAIN{
// We have written out as much as we can...
return sent
}
}
sent += s
}
return sent
}
} catch {
print(error)
}
// second attempt
jsonAckMessageWithDelimiter.withUnsafeBytes {
guard let pointer = $0.baseAddress?.assumingMemoryBound(to: UInt8.self) else {
return
}
write(client, pointer, jsonAckMessageWithDelimiter.count)
}
} catch {
print("Error on received message \(error)")
}
}
}
}
In my node application I can not receive the AckMessage because I get the following error:
Messages are large, You may want to consider smaller messages.
Now from my experience from Windows and Linux I know that \f is the delimiter that should indicate the end of the message. I am sending it at the end of my json but it is somehow not recognized.
What could be the problem? Is the delimiter wrong? Is the buffersize a Problem?
When logging what I send it says that it has sent all 61 bytes as expected.
For anyone having this problem using "\u{000C}" instead of "\f" is the solution.

How to edit/replace embeds in discordjs-commando

I am making a Type racing minigame with my discord bot, the code works... but I want to change the messages it sends to embeds, im new to Commando and it wont let me use the discord.js functions im used to using
I need to change all the bots responses to embeds, and make it so when it sends a new embed it just edits the old one so it isnt spamming messages. Here is my code:
const Commando = require('discord.js-commando')
const { words } = require('../../util/fast-type-words')
const example = {
channelId: {
message: 'message object',
stage: 'string',
counter: 'number',
currentWord: 'string',
remainingWords: ['words here'],
points: {
userId: 'points',
},
},
}
const games = {}
const stages = {
STARTING: (counter) => {
return `A new "fast type" game is starting in ${counter}s!`
},
IN_GAME: (word) => {
let spacedWord = ''
for (const character of [...word]) {
spacedWord += character
spacedWord += ' '
}
return `The new word is **${spacedWord}**!`
},
ENDING: (points) => {
const sorted = Object.keys(points).sort((a, b) => {
return points[b] - points[a]
})
let results = ''
for (const key of sorted) {
const amount = points[key]
results += `<#${key}> had ${amount} point${amount === 1 ? '' : 's'}\n`
}
return `The game is now over Here's how everyone did:\n\n${results}------------------`
},
}
const selectWord = (game) => {
game.currentWord =
game.remainingWords[Math.floor(Math.random() * game.remainingWords.length)]
const index = game.remainingWords.indexOf(game.currentWord)
game.remainingWords.splice(index, 1)
}
const gameLoop = () => {
for (const key in games) {
const game = games[key]
const { message, stage } = game
if (stage === 'STARTING') {
let string = stages[stage](game.counter)
message.edit(string)
if (game.counter <= 0) {
game.stage = 'IN_GAME'
game.counter = 15
selectWord(game)
string = stages[game.stage](game.currentWord)
message.edit(string)
}
} else if (stage === 'IN_GAME') {
if (game.counter <= 0) {
game.stage = 'ENDING'
const string = stages[game.stage](game.points)
message.edit(string)
// Delete the game
delete games[key]
continue
}
}
--game.counter
}
setTimeout(gameLoop, 1000)
}
module.exports = class FastTypeGame extends Commando.Command {
constructor(client) {
super(client, {
name: 'fasttype',
group: 'games',
memberName: 'fasttype',
description: 'Starts a fast type game',
userPermissions: ['ADMINISTRATOR'],
})
client.on('message', (message) => {
const { channel, content, member } = message
const { id } = channel
const game = games[id]
if (game && game.currentWord && !member.user.bot) {
message.delete()
if (
game.stage === 'IN_GAME' &&
content.toLowerCase() === game.currentWord.toLowerCase()
) {
game.currentWord = null
const seconds = 2
const { points } = game
points[member.id] = points[member.id] || 0
message
.reply(`You won! +1 point (${++points[member.id]} total)`)
.then((newMessage) => {
newMessage.delete({
timeout: 1000 * seconds,
})
})
setTimeout(() => {
if (game.stage === 'IN_GAME') {
selectWord(game)
const string = stages[game.stage](game.currentWord)
game.message.edit(string)
}
}, 1000 * seconds)
}
}
})
gameLoop()
}
async run(message) {
const { channel } = message
message.delete()
channel.send('Preparing game...').then((message) => {
games[channel.id] = {
message,
stage: 'STARTING',
counter: 5,
remainingWords: [...words],
points: {
'719805930547445772': 4,
'723819104045105172': 1,
},
}
})
}
}
First change embeded content is not related to discord.js-commando to change the content of sended embeded message you need to get Message Object then using edit() method to pass the new embed content to it:
-Bonus: You can also edit text message into embed message.
Docs for edit method: https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=edit
Example code:
let youCurrentMessage = await channel.send(embedContent);
yourCurrentMessage.edit(newEmbedContent);
yourCurrentMessage.edit(newEmbedContent2);
// If you edit message in other command , session.You need message id
let yourCurrentMessage = await msg.channel.messages.fetch(editMessageId);
yourCurrentMessage.edit(newEmbedContent);

Send signed transaction from nodejs to private SmartContract using webjs in Quorum network not working

Context
I have a quorum network mounted following the example of 7nodes. In node 1 I have deployed a smart contract privately, putting the public key of this "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo=" in the private form.
My goal is to make a transfer to this smart contract, to execute one of its functions. Being a private contract the transfer has to be signed.
All this from a nodejs server.
Code
The smart contract is the following:
pragma solidity ^0.4.19;
contract SimpleStorage {
uint storedData;
uint secondData;
uint TData;
function set(uint x) external {
storedData = x;
}
function setSecond(uint x) external {
secondData = x;
}
function setT(uint x) external {
TData = x;
}
function get() external view returns (uint retVal) {
return storedData;
}
function getSecond() external view returns (uint retVal) {
return secondData;
}
function getT() external view returns (uint retVal) {
return TData;
}
}
The code in nodejs is the following:
const Web3 = require('web3');
const EthereumTx = require('ethereumjs-tx');
const contract = require('truffle-contract');
const simpleStorageInterface = require("./contracts/SimpleStorage.json");
var web3 = new Web3(
new Web3.providers.HttpProvider('http://172.10.4.159:22000')
);
var generalInfo = {
contractAddress: "0x1932c48b2bf8102ba33b4a6b545c32236e342f34",
account: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
keystore: {"address":"ed9d02e382b34818e88b88a309c7fe71e65f419d","crypto":{"cipher":"aes-128-ctr","ciphertext":"4e77046ba3f699e744acb4a89c36a3ea1158a1bd90a076d36675f4c883864377","cipherparams":{"iv":"a8932af2a3c0225ee8e872bc0e462c11"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"8ca49552b3e92f79c51f2cd3d38dfc723412c212e702bd337a3724e8937aff0f"},"mac":"6d1354fef5aa0418389b1a5d1f5ee0050d7273292a1171c51fd02f9ecff55264"},"id":"a65d1ac3-db7e-445d-a1cc-b6c5eeaa05e0","version":3},
bytecode: "0x608060405234801561001057600080fd5b506101ec806100206000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631b03316f1461007d57806322554f34146100a857806360fe47b1146100d35780636d4ce63c14610100578063b698c1291461012b578063f5f3194114610158575b600080fd5b34801561008957600080fd5b50610092610185565b6040518082815260200191505060405180910390f35b3480156100b457600080fd5b506100bd61018f565b6040518082815260200191505060405180910390f35b3480156100df57600080fd5b506100fe60048036038101908080359060200190929190505050610199565b005b34801561010c57600080fd5b506101156101a3565b6040518082815260200191505060405180910390f35b34801561013757600080fd5b50610156600480360381019080803590602001909291905050506101ac565b005b34801561016457600080fd5b50610183600480360381019080803590602001909291905050506101b6565b005b6000600154905090565b6000600254905090565b8060008190555050565b60008054905090565b8060018190555050565b80600281905550505600a165627a7a723058209cc3ec1ccb2383d74522ba2e5974347862883f4c4aa826bb69e6e1cfcc5bdd110029",
interface: [{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"setSecond","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"setT","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getSecond","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getT","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}],
privateFor: "BULeR8JyUWhiuuCMU/HLA0Q5pzkYT+cHII3ZKBey3Bo="
}
web3.eth.getAccounts().then(async (_result) => {
// Set web3 default account
web3.eth.defaultAccount = _result[0];
// Get truffle-contract
let myContract = contract(simpleStorageInterface);
// Set provider
myContract.setProvider(web3.currentProvider);
if (typeof myContract.currentProvider.sendAsync !== "function") {
myContract.currentProvider.sendAsync = function() {
return myContract.currentProvider.send.apply(
myContract.currentProvider, arguments
);
};
}
// Instanciate the contract
var contractInstance = new web3.eth.Contract(simpleStorageInterface.abi, generalInfo.contractAddress);
// Function data
let encodedABI = contractInstance.methods.set(123).encodeABI();
let nonce = await web3.eth.getTransactionCount(web3.eth.defaultAccount);
// Transaction
let tx = {
nonce: web3.utils.toHex(nonce),
from: generalInfo.account,
to: generalInfo.contractAddress,
gas: 2000000,
gasPrice: 0,
data: encodedABI,
privateFor: [generalInfo.privateFor]
}
let decrypt = web3.eth.accounts.decrypt(generalInfo.keystore, "");
// Remove 0x from private key
var privateKey = decryptKey.privateKey.substring(2);
var bufferPK = new Buffer(privateK, 'hex');
// Generate transaction using "ethereumjs-tx"
var transaction = new EthereumTx(tx);
// Sign transaction
transaction.sign(bufferPK);
// Send signed transaction
web3.eth.sendSignedTransaction("0x" + transaction.serialize().toString('hex'), (_err, _res) => {
if(_err){
console.error("ERROR: ", _err);
} else {
console.log("Success: ", _res);
}
}).on('confirmation', (confirmationNumber, receipt) => {
console.log('=> confirmation: ' + confirmationNumber);
})
.on('transactionHash', hash => {
console.log('=> hash');
console.log(hash);
})
.on('receipt', receipt => {
console.log('=> reciept');
console.log(receipt);
})
.on('error', console.error);
});
Question and problem
The transaction is executed successfully, but the new value "123" is not changed in the smart contract. Only if I unlock the account before the transaction await web3.eth.personal.unlockAccount (account, "") works really, but I do not want to be blocking and unblocking the account for security reasons.
A correct transfer would be the following:
{
blockHash: "0xe5a2df3f592392c71f9995d697721c046f60c81d2988418b0c7b929cb17a0cee",
blockNumber: 2190,
from: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
gas: 90000,
gasPrice: 0,
hash: "0x24df9e01d9fdb7acc7a2842dcdd1d93a37e7be7885ef469a262d8a690f7143f3",
input: "0xb0101ef545cf42bb490bca4fac873ea06d989abf1fbdc89f7dfd09014c085f163c371efa5acac2b43c9dec5cb20bd11e853069a99f4bcb938d6fdcd6f2918333",
nonce: 31,
r: "0x9851006a766b4bd75051cdba9c06b6d251125d68894983eee3a4c1a53a03d77a",
s: "0x1696039cedf14a82147c858bc17896664c9c74bda313307dbf9386b7d6893938",
to: "0x1932c48b2bf8102ba33b4a6b545c32236e342f34",
transactionIndex: 0,
v: "0x25",
value: 0
}
Mine looks like this:
{
blockHash: "0x6a2aacceabe984b2c368fa9ca7c245065924dd6d88e30f81311e2a5a7e2aeab8",
blockNumber: 2119,
from: "0xed9d02e382b34818e88b88a309c7fe71e65f419d",
gas: 2000000,
gasPrice: 0,
hash: "0x4a918c1641478c1f229e7cdfff93669a6e08b37555eafe871fc3b05717cbcb79",
input: "0x60fe47b1000000000000000000000000000000000000000000000000000000000000007b",
nonce: 30,
r: "0xac64a34de4bf0c2d3f1d8da6af3d38ee12be38846f744004eeef460ad94b528e",
s: "0x10e642925665877c4e2571a2f835af68c025417574462ffc4864e6128e4a4deb",
to: "0x1932c48b2bf8102ba33b4a6b545c32236e342f34",
transactionIndex: 0,
v: "0x1c",
value: 0
}
The difference is the property "v", the value that is being fixed in my transfer is not correct, it has to be 0x25 or 0x26 to identify them as private transfers. I do not understand why these values are not setting well, helpme please.

Resources