How do I use ABI with Next.js? - next.js

Problem
I'm doing some development using Next.js and ZKSwap API, but I can't figure out how to use the ABI of the deployed smart contract.
Specifically, I want to call this DepositETH.
https://en.wiki.zks.org/interact-with-zkswap/make-transaction#deposit-eth
And it seems that I need to configure this ABI to call it, but I don't know how to configure it.
https://en.wiki.zks.org/interact-with-zkswap/make-transaction#abis
What I Did
I implemented it as follows, but it didn't work.
import { Wallet, Contract, utils } from 'ethers'
import Web3 from 'web3'
import zkswapABI from '../src/zkswap.ABI.json'
const Web3EthAbi = require('web3-eth-abi');
export default function zkswap() {
//try2
let ABI = zkswapABI
const wallet = new Wallet('0x1c1a49fea9a4ede1dc8e582639f498d41fa3c4a9e2ab2b9d740a4a3ec14e1cbf')
const contract = new Contract('0x8ECa806Aecc86CE90Da803b080Ca4E3A9b8097ad', ABI, wallet)
async function depositETH(amount) {
const tx = await contract.depositETH(wallet.address, {
value: utils.parse(amount)
})
return tx
}
depositETH('0.5').then(console.log)
return (
<div>
<section className="h-screen w-4/5 max-w-5xl mx-auto flex items-center justify-center flex-col">
<h1 className="mb-4 text-green-500 text-3xl">sample</h1>
<p className="mb-2 text-center"> ZKSwap </p>
<button className="btn-blue" onClick={depositETH}> Deposit ETH</button>
</section>
</div>
)
}
Error
In fact, when I tried to 'yarn dev', I got an error like this
TypeError: ethers__WEBPACK_IMPORTED_MODULE_1__.utils.parse is not a function

Related

Kabab case CSS classes in Next.js [duplicate]

I am using SCSS modules for my components in React/Next.js but I can't figure out how to import kebab-case classes.
At the moment, I am just writing all my SCSS classes in camelCase but this isn't ideal as this means I cannot make use of SCSS cascading.
(I'm still learning React am I'm not so great at making dynamic components myself so I am sticking to React Strap for now.)
Essentially, I want to write
.company-logo
instead of:
.companyLogo
EDIT: className={styles['company-logo']} causes an unexpected token error
Here is my Component:
import styles from './styles/Navbar.module.scss'
const NavComponent = (props) => {
const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);
return (
<div>
<img src="../ss-logo.png" alt="Logo" className={styles.companyLogo}/>
</div>
);
}
export default NavComponent;
And my SCSS:
.companyLogo {
height: 3rem;
}
className={styles['company-logo']}
should be what you want.
You can use the object key [] syntax.
<img src="..." className={styles['company-logo']}`
<img src="../ss-logo.png" alt="Logo" className={`${style['company-logo']}`}/>
inline:
<img src="../ss-logo.png" alt="Logo" className={`${styles["company-logo"]}`}/>
variable:
var logo = classNames({
[`${styles["company-logo"]}`]: true,
});
return (
<div>
<img src="../ss-logo.png" alt="Logo" className={logo}/>
</div>
)

Next.js 13 Updating SSR Component state after action

I am learning Nextjs for the first time, and have experimented by creating a small web app that allows someone to simply register then login. Everything works, except one small issue.
On the page, you can see your status. If you are logged in, it shows your username. If not, it provides a link to the sign in page.
This "Sign In" button is a part of the UserInfoBar component, which is a SSR-component.
The problem is, that when you successfully login, and are redirected to the homepage with router.push('/'), the "Sign In" link is not replaced with your username.
It is only when you refresh the page that your username will show.
I am really at a loss here. The only solution that I can think of is to make UserInfoBar a client component, but then I would have to manually retrieve the session with a fetch call.
Is there not a way to address this from the server side?
src/app/components/UserInfoBar.tsx
import React from 'react'
import Link from 'next/link'
import { getSession } from '../../lib/session'
export default async function UserInfoBar() {
let sessionData = getSession();
console.log('on the server')
console.log(sessionData)
return (
<div className="flex-grow text-right px-2 py-1 text-white">
{sessionData ?
sessionData.username :
<Link href="/signin" className='px-2 py-1 text-white '>Sign In</Link>}
</div>
)
}
src/app/Header.tsx
import React from 'react'
import Link from 'next/link'
import { Suspense } from 'react';
import UserInfoBar from './components/UserInfoBar'
export default function Header() {
return (
<header className='flex justify-center bg-slate-700 mb-7'>
<div className='flex max-width space-x-4 p-4'>
<Link href="/" className='px-2 py-1 text-white '>Home</Link>
<Link href="/decks" className='px-2 py-1 text-white '>Decks</Link>
<Link href="/signup" className='px-2 py-1 text-white '>About</Link>
<Suspense fallback={<p>loading...</p>}>
<UserInfoBar />
</Suspense>
</div>
</header>
)
}
src/app/page.tsx
import React from 'react'
export default function Page() {
return (
<div>
<h2 className="text-4xl font-extrabold text-slate-700">Demo</h2>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam faucibus erat a gravida ultricies.
</div>
)
}
src/app/lib/session.ts
import { cookies } from 'next/headers';
import jwt from 'jsonwebtoken'
export const getSession = () => {
const nxtCookies = cookies();
if (nxtCookies.has('session')) {
const cookie = nxtCookies.get('session');
let sessionData = jwt.verify(cookie.value, process.env.ACCESS_TOKEN_SECRET, (err, user) => {
if (err) return false;
return user;
});
if (sessionData) return sessionData;
}
return false;
}
While re-reading the Next.js docs, I missed this crucial part:
Invalidating the Cache: The cache can be invalidated using
router.refresh(). For more information, see the API reference. In the
future, mutations will automatically invalidate the cache.
Simply adding router.refresh() before my router.push() call fixed the problem.

Google Photos API - Automatic Scaling?

I've been making a website to showcase my personal photography, and I've been getting my photos from Google Photos, using their features. (There's a medium post on how to do this)!
However, one problem I have been having is with scaling. I would like my images to be as quality as possible but also at a small enough size for them to fit into a grid on my page. However, when I use the built in parameters to do this (according to the docs) scaling is not preserved!
Example:
My page's code is as follows:
const axios = require('axios');
const Image = require('next/image');
const _ = require('lodash');
export default function Home({ pictures }) {
return (
<div>
<div className="hero min-h-screen" style={{ backgroundImage: 'url(https://lh3.googleusercontent.com/wwilPCF5L98Osl7_HVohVi34EP4SHUNKbxCe-fBooyNcTdvAWawcP3paqGxvAW3gCzXBl4aQOT_oxwYuXXaMG3ICM7cOkWJH6eYcozUqr9agShnjQu8kWFsPxtL7WD7H5sF5rkR9Vdk=w2048)' }}>
<div className="hero-overlay bg-opacity-60" />
<div className="hero-content text-center text-neutral-content">
<div className="max-w-md">
<h1 className="mb-5 text-5xl font-bold">Photography</h1>
<p className="mb-5">Aside from programming, I also love photography! </p>
</div>
</div>
</div>
<div className="flex flex-col flex-wrap m-10">
<div className="flex flex-row basis-1 flex-wrap m-4">
{
pictures.map(((x) => (
<img src={`${x}`} alt="Hello." key={`${x}?`} className=" flex-col flex-auto m-3 rounded-md shadow-md" />
)))
}
</div>
</div>
</div>
);
}
export async function getServerSideProps({ req, res }) {
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
const regex = /\["(https:\/\/lh3\.googleusercontent\.com\/[a-zA-Z0-9\-_]*)"/g;
function extractPhotos(content) {
const links = new Set();
let match;
while (match = regex.exec(content)) {
links.add(match[1]);
}
return Array.from(links);
}
async function getAlbum(id) {
const response = await axios.get(`https://photos.app.goo.gl/${id}`);
const photos = _.shuffle(extractPhotos(response.data));
return photos;
}
const pictures = await getAlbum('ZbGaHdrs62q5Jyrk8');
return {
props: { pictures }, // will be passed to the page component as props
};
}
How can I ensure the images are properly scaled? Is this even possible? Will I need some CSS trick? Thanks!

how to fix nextjs prerender error - vercel deployment?

How do I troubleshoot this problem this deployment issue? I am following this tutorial. My node_modules and .next are ignored and not pushed to github. It works locally but can't seem to deploy. I have supplied both the component code as well as the page it's exported on. Let me know if you can see what I am missing.
https://www.youtube.com/watch?v=V4SVNleMitE
deployment errors
Error occurred prerendering page "/components/BlogPosts". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot read property 'fields' of undefined
at BlogPosts (/vercel/path0/.next/server/chunks/130.js:39:12)
at d (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:33:498)
at bb (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:36:16)
at a.b.render (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:42:43)
at a.b.read (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:41:83)
at Object.exports.renderToString (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.node.production.min.js:52:138)
at Object.renderPage (/vercel/path0/node_modules/next/dist/server/render.js:673:46)
at Object.defaultGetInitialProps (/vercel/path0/node_modules/next/dist/server/render.js:315:51)
at Function.getInitialProps (/vercel/path0/.next/server/pages/_document.js:645:16)
at Object.loadGetInitialProps (/vercel/path0/node_modules/next/dist/shared/lib/utils.js:69:29)
component blog posts
export default function BlogPosts({post }) {
const {title, information,slug , thumbnail} = post.fields
return (
<div>
<div className='container w-50 h-25 mt-4'>
<Image
className='nav'
src={'https:' + thumbnail.fields.file.url}
width={thumbnail.fields.file.details.image.width}
height={thumbnail.fields.file.details.image.height}
/>
</div>
<div>
<div>
<h4 className=''>{title}</h4>
<Link href={'/contentslug/' + slug}>
<a className='btn btn-primary text-white'>Read more</a>
</Link>
</div>
</div>
</div>
)
}
Pages/Posts
import {createClient} from 'contentful'
import BlogPosts from './components/BlogPosts'
import Nav from './components/Nav'
import Logo from './components/Logo'
export async function getStaticProps() {
const client = createClient({
space: process.env.NEXT_PUBLIC_CONTENTFUL_ID,
accessToken: process.env.NEXT_PUBLIC_CONTENTFUL_TOKEN,
})
const res = await client.getEntries({content_type: 'posts'})
return {
props: {
posts: res.items ,
revalidate: 1
}
}
}
export default function Home({posts}) {
console.log(posts);
return (
<div>
<Logo/>
<Nav/>
<div className="container text-center display-5">
{posts.map(post => (
<BlogPosts key={post.sys.id} post={post}/>
))}
</div>
</div>
)
}
You have fields of undefined. this might be caused because of some strange deploying behavior if you are 100% sure your code works.
How to fix (probably):
Build your project locally. if it works, follow the next step
Comment your code in BlogPosts, inside the exported component. The code must work, so your exported component will be empty but working.
Push this code to Vercel.
Uncommit your code. (done at point 2)
Push again.
P.S. this behavior with API is sometimes caused because of API middleware you reworked.

getting this npm react component to work with meteor

Using react-typeahead-component
I used browserify to change it from npm into a meteor local package. Nothing is showing on the screen when i run meteor.
OptionTemplate.jsx
module.exports = React.createClass({
render: function() {
return (
<div>
<p>HELLO</p>
</div>
);
},
handleChange: function(event) {
console.log('HELLO');
}
});
main.jsx
var OptionTemplate = require('./OptionTemplate.jsx');
SearchBox = React.createClass({render() {
return (
<div className="col-xs-12 col-lg-12">
<OptionTemplate />
</div>
)}
});
You aren't using components properly. You might want to re-read the react documentation.
In your main.jsx, you are importing the component 'OptionTemplate' but you are trying to render the component 'Typeahead' and passing in 'OptionTemplate' as a prop. The 'Typeahead' component now lives in 'OptionTemplate'. Your main.jsx should like like:
var OptionTemplate = require('./OptionTemplate.jsx');
SearchBox = React.createClass({render() {
return (
<div className="col-xs-12 col-lg-12">
<OptionTemplate />
</div>
)}
});

Resources