I am working on a smart contract interaction, I started writing the contract called BuyCoffee:
contract BuyCoffee {
struct Author {
address wallet_address;
uint256 balance;
}
struct Coffee {
address author_wallet_address;
address sender_wallet_address;
uint256 value;
}
Coffee[] public coffee;
mapping (address => Author) public authors;
uint256 public total_contract_balance;
function getContractBalance() public view returns (uint256) {
return total_contract_balance;
}
...
function buymeacoffee(address author_wallet_address, address sender_wallet_address, uint256 value) public {
coffee.push(Coffee({
author_wallet_address: author_wallet_address,
sender_wallet_address: sender_wallet_address,
value: value
}));
authors[author_wallet_address].balance += value;
total_contract_balance += value;
}
}
For the frontend app, I am using the library Ether and building a metamask_controller.js
import { Controller } from "#hotwired/stimulus";
import { ethers } from "ethers";
import abi from "../contract.json" assert { type: "json" };
export default class extends Controller {
...
async buyCoffee() {
try {
const authorWalletAddress = "0x5FF0...f16F3D2";
const senderWalletAddress = userAddress;
const price = this.priceTarget.innerText;
console.log("price: ", price);
console.log("authorWalletAddress: ", authorWalletAddress);
console.log("senderWalletAddress: ", senderWalletAddress);
// execute transaction
const transaction = await contract.buymeacoffee(
authorWalletAddress,
senderWalletAddress,
{ value: ethers.utils.parseEther(price)}
);
// console.log("Processing...", transaction.hash);
await transaction.wait();
// reload the whole page
window.location.reload();
}
catch (error) {
console.log(error);
alert("Transaction failed!");
}
}
But look like that I am having an issue when calling the buyCoffee function, the console log show me the correct values:
price: 0.001
authorWalletAddress: 0x5FF....F3D2
senderWalletAddress: 0x7da....1721
Then I get the error invalid BigNumber value (argument="value", value={"value":{"type":"BigNumber","hex":"0x038d7ea4c68000"}}, code=INVALID_ARGUMENT, version=bignumber/5.7.0)
How could I solve that? Look like is something about the price that has to change from 0.001 to big number
We always pass values as string:
// you could use BN too
{ value: ethers.utils.parseEther(price.toString())}
Related
pragma solidity =0.7.6;
pragma abicoder v2;
import "https://github.com/Uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
}
contract MultiSwap {
address public owner;
address public balance;
constructor() {
owner == msg.sender;
}
address public constant routerAddress =
0xE592427A0AEce92De3Edee1F18E0157C05861564;
ISwapRouter public immutable swapRouter = ISwapRouter(routerAddress);
address public constant SHUBYDAI = 0xe742A911ffFAEc86786bd2246Dd035F6Aa55aE2B;
address public constant SHUBYUSDC = 0xA61C9829209b75741bBB9f682483B3A4C3e4E924;
IERC20 public shubyToken = IERC20(SHUBYDAI);
function swapExactInputMultihop(uint amountIn)
external
returns (uint amountOut)
{
shubyToken.transfer(
address(this),
amountIn
);
shubyToken.approve(address(swapRouter), amountIn);
ISwapRouter.ExactInputParams memory params = ISwapRouter
.ExactInputParams({
path: abi.encodePacked(
SHUBYDAI,
uint24(3000),
SHUBYUSDC,
uint24(3000),
SHUBYDAI
),
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0
});
amountOut = swapRouter.exactInput(params);
}
function transferIERC20(IERC20 token, address to, uint256 amount) public {
require(msg.sender == owner, "Only the owner can use this function");
uint256 erc20Balance = token.balanceOf(address(this));
require(amount <= erc20Balance, "balance is low");
token.transfer(to, amount);
}
function SeeBalance(IERC20 token) public view {
IERC20(token).balanceOf(address(this));
}
}
when i try to interact with this contract on remix and i try to run the seeBalance function it doesn't work, the message i get is.
[block: txIndex:]from: 0x241...8Be5fto: 0xFC4c5cE47f2E9361B28E8f6B486668dB61730A81 0xFC4...30A81value: 0 weidata: 0xbbb...5ae2blogs: 0hash:
decoded output -
i have transfered 4000 ShubyDAI which is the token i want to see the token for but i dont get a value.
Could someone help please.
I guess the code should be as below.
function SeeBalance(IERC20 token) public view returns (uint256) {
return IERC20(token).balanceOf(address(this));
}
I have to encrypt a credit card using https://unpkg.com/browse/openpgp#5.4.0/dist/
Then I import it as a module, cc processors code not mine.
<script type="module">
import * as openpgp from './js/openpgp.min.mjs';
import { createMessage, encrypt, readKey } from 'openpgp'
// Object to be encrypted
interface CardDetails {
number?: string, // required when storing card details
cvv?: string // required when cardVerification is set to cvv
}
// Encrypted result
interface EncryptedValue {
encryptedData: string,
keyId: string
}
const pciEncryptionKey = await getPCIPublicKey()
/**
* Encrypt card data function
*/
return async function(dataToEncrypt: CardDetails): Promise<EncryptedValue> {
const decodedPublicKey = await readKey({ armoredKey: atob(publicKey) })
const message = await createMessage({ text: JSON.stringify(dataToEncrypt) })
return encrypt({
message,
encryptionKeys: decodedPublicKey,
}).then((ciphertext) => {
return {
encryptedMessage: btoa(ciphertext),
keyId,
}
})
}
</script>
This code needs to be invoked when the user click a submit button and then inject the encrypted card into a hidden field.
Any ideas on how to get this to work?
The server has a Meteor Method that returns a GiftList object that contains a Gift set.
The client has a Meteor Call that prints out the result. The Gift set is undefined even though it is initialised and sent by the server. The instance variables don't seem to be included in the response even though the server has sent it.
Gift List
import {Gift} from "../gift/Gift";
export class GiftList {
private _id: number;
private _personName:string;
private _user: User;
private _gifts: Set<Gift>;
get id(): number {
return this._id;
}
set id(value: number) {
this._id = value;
}
get personName(): string {
return this._personName;
}
set personName(value: string) {
this._personName = value;
}
get user(): User {
return this._user;
}
set user(value: User) {
this._user = value;
}
get gifts(): Set<Gift> {
return this._gifts;
}
set gifts(value: Set<Gift>) {
this._gifts = value;
}
}
Gift
import {GiftList} from "../giftlist/GiftList";
export class Gift {
private _id: number;
private _name: string;
private _description: string;
private _isPrivate: boolean;
private _cost: number;
private _giftList: GiftList;
get id(): number {
return this._id;
}
set id(value: number) {
this._id = value;
}
get name(): string {
return this._name;
}
set name(value: string) {
this._name = value;
}
get description(): string {
return this._description;
}
set description(value: string) {
this._description = value;
}
get isPrivate(): boolean {
return this._isPrivate;
}
set isPrivate(value: boolean) {
this._isPrivate = value;
}
get cost(): number {
return this._cost;
}
set cost(value: number) {
this._cost = value;
}
get giftList(): GiftList {
return this._giftList;
}
set giftList(value: GiftList) {
this._giftList = value;
}
}
Server - Meteor Method
Meteor.methods({
"getGiftLists": function (): GiftList[] {
const giftList: GiftList = new GiftList();
giftList.gifts = new Set();
const gift: Gift = new Gift();
gift.name= "Example gift";
gift.description = "Description of gift";
giftList.gifts.add(gift);
// I've printed the value here and the gift list definitely contains gifts as expected.
return [giftList]
}
})
Client - Meteor Call
Meteor.call("getGiftLists", {}, (err: any, res: GiftList[]) => {
if (err) {
alert(err);
} else {
console.dir(res); // Defined
console.log(res.length) // 1
console.dir(res[0].gifts); // Undefined
callback(res);
}
});
Question
Why is the Gift set undefined?
I believe the problem here is that Metoer's EJSON doesn't know how to serialize a Set to be sent to the client. EJSON provides a way to define new types and how they should be serialized and de-serialized. Have a look at the EJSON docs.
https://docs.meteor.com/api/ejson.html
So I have major problem with importing from one class to another and what I have done is in my "main" class which I call
detailsPage.js
import { DetailsPage } from '../tests/detailsPageObj';
const utils = require("../utils/utils");
const assert = require('../node_modules/chai').assert;
const userData = require('../globalContent.json');
describe('Details page', function () {
const detailsPage = new DetailsPage();
// The details page is accessible by the specified URL
it(`Is defined by the URL: ${userData.url}`, async function () {
await detailsPage.navigate();
});
// Details page has a form and it can be filled out with user data
it('Has a form that can receive user data', async function () {
await detailsPage.fillFormWithUserData(); // If you want, make the user data passable to the method
await utils.click(detailsPage.form.buttons.nextStep);
});
if (detailsPage.hasStockConflict) {
// Details page allows the user to fix conflicts in stocks
it('Enables resolution of stock conflicts', async function () {
// Wait for stock to fully load
await browser.sleep(2000);
await detailsPage.clickAllRemoveButtons();
await detailsPage.clickAllDecreaseButtons();
});
}
// Details page allows the user to proceed to the next stage when all conflicts (if any) has been resolved
it('Allows the user to proceed to the next stage of purchasing', async function () {
const nextStepButton = detailsPage.form.buttons.nextStep;
await utils.elementToBeClickable(nextStepButton);
await utils.click(nextStepButton);
});
});
and what I am trying tod o is to get DetailsPage from another script which is called:
detailsPageObj
import { element, by } from 'protractor';
const utils = require("../utils/utils");
const userData = require('../globalContent.json');
export class DetailsPage {
get pageUtils() {
return {
qtyRegex: /^Sorry.*?(\d+)/
}
}
private get fields() {
return {
email: element(by.id('email')),
firstName: element(by.id('firstName')),
lastName: element(by.id('lastName')),
postalCode: element(by.id('postalCode')),
addressOne: element(by.id('addressOne')),
addressTwo: element(by.id('addressTwo')),
phone: element(by.id('phone')),
businessCustomerCB: element(by.id('isBusinessCustomer')),
company: element(by.id('company')),
GST: element(by.id('gst')),
}
}
private get groups() {
return {
address: element(by.css('div#addressGroup.input-container.showHiddenGroup'));
company: element(by.id('companyGroup')),
}
}
private get modals() {
return {
contactModalLink: element(by.id('contactModalLink')),
cross: element(by.className('modal-cross')),
}
}
private get formButtons() {
return {
nextStep: element(by.id('submitIdentityFormButton')),
mobile: this.mobileFormButtons
}
}
private get mobileFormButtons() {
return {
continue: element(by.id('stock-conflict-continue-button')),
removeOutOfStockItems: element(by.css('button[id="removeOutOfStockItems"]')), // I just assumed that this is a part of the form
}
}
private get productFrameMobileButtons() {
return {
stockControll: element.all(by.className('stock-controller mobile')),
remove: element.all(by.className('btn btn-remove btn-outlined mobile')),
}
}
private get productFrameDesktopButtons() {
return {
stockControll: element.all(by.className('stock-controller desktop')),
remove: element.all(by.className('btn btn-remove btn-outlined desktop')),
}
}
get form() {
return {
fields: this.fields,
groups: this.groups,
buttons: this.formButtons,
modals: this.modals
}
}
get productFrame() {
return {
buttons: {
decrease: element.all(by.className("btn left")).first(),
mobile: this.productFrameMobileButtons,
desktop: this.productFrameDesktopButtons
}
}
}
get errors() {
return {
stockConflict: element(by.className('generic-error-heading')),
}
}
}
and what I am trying to do is in detailsPage.js im trying to import detailsPageObj.js but whenever I am trying to do it I do get SyntaxError: Cannot use import statement outside a module.
What am I doing wrong
I don't know what is your environment like, but I experienced a similar problem where my environment used a full build step for creating the target JS code from my sources (e.g. from TypeScript or from ES6+) to a bundled/plain JS.
But then my test environment did not have any build step. So when I executed the tests, it only understood plain JS, which by default in a node.js environment does not recognize import but only require.
You can use import in your node.js code without a build step, but you need to follow some steps, e.g. rename your file from *.js to *.mjs. More details here.
I am creating a frontend app based on Truffle + Webpack, following this tuto : http://truffleframework.com/tutorials/building-testing-frontend-app-truffle-3, and have no uderstanding of JavaScript at all.
The code works on truffle console and the app globally works, except for the function "append_buy_brent", adding a new element to a struct array called buy_orderbook_brent
Solidity :
contract Petroleum{
// Initialisations
address _creator;
uint user_number;
struct Baril_order {
uint price;
uint quantity;
address addr;
}
Baril_order[] buy_orderbook_brent;
mapping(address => uint) account_map;
mapping(uint => uint) user_balance;
mapping(uint => uint) number_of_brent;
function Petroleum() payable{
_creator=msg.sender;
user_number=0;
test=0;
account_map[_creator]=0;
account_map[0x7f8105da4dd1af61da7bf587766103ba8534fcdc]=1;
user_balance[account_map[msg.sender]]=100000;
number_of_brent[account_map[msg.sender]]=5;
number_of_wti[account_map[msg.sender]]=2;
debt[account_map[msg.sender]]=20;
user_balance[account_map[0x7f8105da4dd1af61da7bf587766103ba8534fcdc]]=200000;
number_of_brent[account_map[0x7f8105da4dd1af61da7bf587766103ba8534fcdc]]=7;
number_of_wti[account_map[0x7f8105da4dd1af61da7bf587766103ba8534fcdc]]=10;
debt[account_map[0x7f8105da4dd1af61da7bf587766103ba8534fcdc]]=3;
}
function append_buy_brent(uint price, uint quantity, address addr) payable {
buy_orderbook_brent.push(
Baril_order({
price:price,
quantity: quantity,
addr: addr,
})
);
}
}
JavaScript :
import { default as Web3} from 'web3';
import { default as contract } from 'truffle-contract'
import Petroleum_artifacts from '../../build/contracts/Petroleum.json'
var Petroleum = contract(Petroleum_artifacts);
var accounts;
var account;
var account1;
window.App = {
start: function() {
var self = this;
Petroleum.setProvider(web3.currentProvider);
web3.eth.getAccounts(function(err, accs) {
if (err != null) {
alert("There was an error fetching your accounts.");
return;
}
if (accs.length == 0) {
alert("Couldn't get any accounts! Make sure your Ethereum client is configured correctly.");
return;
}
accounts = accs;
account = accounts[0];
account1 = accounts[1];
self.refreshBalance1();
self.refreshBalance2();
});
},
append_buy_brent: function(){
var self = this;
var price_buy_brent= parseInt(document.getElementById("price_buy_brent").value);
var quantity_buy_brent=parseInt(document.getElementById("quantity_buy_brent").value);
this.setStatus("Initiating transaction... (please wait)");
var petro;
Petroleum.deployed().then(function(instance) {
petro = instance;
return petro.append_buy_brent(price_buy_brent,quantity_buy_brent, account, {from: account, value: web3.toWei(1000, "ether")});
}).then(function(value) {
self.setStatus("Transaction complete!");
self.refreshBalance1();
self.refreshBalance2();
}).catch(function(e) {
console.log(e);
self.setStatus("Error placing buy_brent; see log.");
});
},
}
Log :
Error: VM Exception while processing transaction: invalid JUMP at
d8abbe98e23bfa2cd66729f537c8dd23bb72c25425af350243627a30533c3b73/a8c9aca1a9b5fd638a6aa025545e1274787f3456:790
I hope I gave enough information, first time here. Thanks a lot.
it looks like a EVM bug. Could you try without putting both the contract deployment and the function call in 2 different transactions ?
https://github.com/ethereumjs/testrpc/issues/196