Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: lsp4 uploads and network selection #156

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions jest.config.cjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
const esModules = ['@lukso/lsp-smart-contracts', '@lukso/lsp-factory.js'].join(
'|'
)
const esModules = [
'@lukso/lsp-smart-contracts',
'@lukso/lsp-factory.js',
'@web3-onboard',
'nanoid',
'@lukso/web3-onboard-config',
'@tsndr/cloudflare-worker-jwt',
].join('|')

module.exports = {
transform: {
'^.+\\.vue$': '@vue/vue3-jest',
'^.+\\.tsx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.json' }],
'^.+\\.(t|j)sx?$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.json' }],
},
setupFilesAfterEnv: ['<rootDir>/tests/setup-env.ts'],
transformIgnorePatterns: [`/node_modules/(?!${esModules})`],
transformIgnorePatterns: [`/node_modules/(?!(${esModules}))`],
testEnvironment: 'jsdom',
moduleFileExtensions: ['js', 'ts', 'json', 'vue'],
moduleNameMapper: {
Expand Down
3 changes: 3 additions & 0 deletions jest.setup.cjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
module.exports = async () => {
process.env.TZ = 'UTC'

global.crypto = require('isomorphic-webcrypto')
console.log(global.crypto)
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
"@lukso/up-provider": "^0.1.3",
"@lukso/web3-onboard-config": "1.1.2",
"@pinata/sdk": "^2.1.0",
"@tsndr/cloudflare-worker-jwt": "^2.5.3",
"@types/isomorphic-fetch": "^0.0.39",
"@walletconnect/ethereum-provider": "2.16.0",
"@walletconnect/sign-client": "2.16.0",
Expand All @@ -41,6 +40,7 @@
"filesize": "10.0.12",
"https-browserify": "1.0.0",
"isomorphic-fetch": "^3.0.0",
"isomorphic-webcrypto": "^2.3.8",
"siwe": "1.1.6",
"tslib": "^2.6.2",
"vue": "^3.4.21",
Expand Down
21 changes: 10 additions & 11 deletions src/components/endpoints/Assets.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@ import { Lsp4Metadata, Token } from '@/types'
import { ContractStandard } from '@/enums'
import CustomSelect from '@/components/shared/CustomSelect.vue'
import { useLspFactory } from '@/compositions/useLspFactory'
import { addTokenToLocalStore, recalculateAssets } from '@/helpers/tokenUtils'
import {
addTokenToLocalStore,
encodeAssetMetadata,
recalculateAssets,
} from '@/helpers/tokenUtils'
import { DeployedERC20Token, useERC20 } from '@/compositions/useErc20'
import { LSP8_TOKEN_ID_FORMAT } from '@lukso/lsp-smart-contracts'
import { LSP4_TOKEN_TYPES } from '@lukso/lsp4-contracts'
import { uploadAssetData } from '@/utils/uploadAssetData'
import {
DeployedLSP7DigitalAsset,
DeployedLSP8IdentifiableDigitalAsset,
Expand Down Expand Up @@ -70,6 +75,8 @@ const create = async () => {
const erc725AccountAddress = getState('address')
isTokenPending.value = true

const assetMetadata = await uploadAssetData(lsp4Metadata.value)
JeneaVranceanu marked this conversation as resolved.
Show resolved Hide resolved
const metadataJsonUrl = encodeAssetMetadata(assetMetadata)
try {
const { deployLSP7DigitalAsset, deployLSP8IdentifiableDigitalAsset } =
useLspFactory()
Expand All @@ -92,11 +99,7 @@ const create = async () => {
tokenType: LSP4_TOKEN_TYPES.TOKEN,
isNFT: !!token.value.isNonDivisible,
creators: toRaw(creators.value),
digitalAssetMetadata: {
LSP4Metadata: {
...lsp4Metadata.value,
},
},
digitalAssetMetadata: metadataJsonUrl,
}
console.log(digitalAssetData)
deployedAsset = await deployLSP7DigitalAsset(digitalAssetData)
Expand All @@ -111,11 +114,7 @@ const create = async () => {
controllerAddress: erc725AccountAddress,
tokenType: LSP4_TOKEN_TYPES.COLLECTION,
creators: toRaw(creators.value),
digitalAssetMetadata: {
LSP4Metadata: {
...lsp4Metadata.value,
},
},
digitalAssetMetadata: metadataJsonUrl,
tokenIdFormat: tokenIdType.value,
}
console.log(digitalAssetData)
Expand Down
32 changes: 23 additions & 9 deletions src/components/endpoints/GetNetworkId.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import {
NETWORKS,
setNetworkConfig,
} from '@/helpers/config'
import { hexToNumber } from 'web3-utils'
import { NetworkInfo } from '@/interfaces/network'
import { ref, watch } from 'vue'
import { onMounted, ref, watch } from 'vue'
import { numberToHex } from 'web3-utils'

const { notification, clearNotification, hasNotification, setNotification } =
useNotifications()
const web3 = useWeb3Connection()

const defaultNetworkConfig = getSelectedNetworkConfig()
const defaultNetwork: NetworkInfo = {
...defaultNetworkConfig,
}
// const defaultNetwork: NetworkInfo = {
// ...defaultNetworkConfig,
// }

const networkId = ref('')
const err = ref('')
const activeNetwork = ref<NetworkInfo>(defaultNetwork)
const activeNetwork = ref<NetworkInfo>(defaultNetworkConfig)
watch(
() => getSelectedNetworkConfig(),
() => {
Expand All @@ -44,6 +44,7 @@ const getNetworkId = async () => {
}

const changeNetwork = async () => {
if (!activeNetwork.value) return
try {
await web3.sendRequest({
method: 'wallet_switchEthereumChain',
Expand All @@ -63,20 +64,22 @@ const changeNetwork = async () => {
}

const changeDappNetwork = async () => {
if (!activeNetwork.value) return
try {
let currentChainId = getSelectedNetworkConfig().chainId
if (currentChainId !== activeNetwork.value.chainId) {
setNetworkConfig(activeNetwork.value.chainId)
currentChainId = getSelectedNetworkConfig().chainId
location.reload()
}
location.reload()
} catch (error) {
console.error(error)
setNotification((error as unknown as Error).message, 'danger')
}
}

const addNetwork = async () => {
if (!activeNetwork.value) return
try {
await web3.sendRequest({
method: 'wallet_addEthereumChain',
Expand All @@ -94,6 +97,17 @@ const addNetwork = async () => {
setNotification((addError as unknown as Error).message, 'danger')
}
}

onMounted(() => {
const selectedNetworkChainId = getSelectedNetworkConfig()
const networkInfo = networks.find(
(element: NetworkInfo) =>
hexToNumber(element.chainId) === selectedNetworkChainId.chainId
)
if (networkInfo) {
activeNetwork.value = networkInfo
}
})
</script>

<template>
Expand Down Expand Up @@ -124,7 +138,7 @@ const addNetwork = async () => {
data-testid="getNetworkId"
@click="changeNetwork"
>
Switch Network to {{ activeNetwork.name }}
Switch Network to {{ activeNetwork?.name }}
</button>
</div>
<div>
Expand All @@ -142,7 +156,7 @@ const addNetwork = async () => {
data-testid="changeDappNetworkButton"
@click="changeDappNetwork"
>
Switch Network in DApp to {{ activeNetwork.name }}
Switch Network in DApp to {{ activeNetwork?.name }}
</button>
<div style="padding-top: 8px">
DApp uses <b>{{ defaultNetworkConfig.name }}</b> network.
Expand Down
4 changes: 4 additions & 0 deletions src/components/endpoints/__tests__/Assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ jest.mock('@/compositions/useErc20', () => ({
}),
}))

jest.mock('@/helpers/env', () => ({
PUBLIC_API_SHARED_SECRET: '123',
}))

jest.mock('@/compositions/useWeb3Connection', () => ({
__esModule: true,
default: () => ({
Expand Down
9 changes: 2 additions & 7 deletions src/compositions/__tests__/useLspFactory.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { useLspFactory } from '@/compositions/useLspFactory'
import { LSPFactory } from '@lukso/lsp-factory.js'

jest.mock('@lukso/lsp-factory.js', () => ({
LSPFactory: jest.fn(),
jest.mock('@/helpers/env', () => ({
PUBLIC_API_SHARED_SECRET: '123',
}))

jest.mock('@/compositions/useWeb3Connection', () => ({
Expand All @@ -22,10 +21,6 @@ describe('can produce LSP Factory', () => {
useLspFactory()
})

it('should be called with window.lukso', async () => {
expect(LSPFactory).toBeCalledWith({}, { chainId: 4201 })
})

it('should return null for empty chain id', async () => {
window.lukso = undefined
expect(useLspFactory).toThrow('Extension not installed')
Expand Down
4 changes: 2 additions & 2 deletions src/helpers/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ export const NETWORKS: { [K in NetworkType]: NetworkInfo } = {
erc721TokenWithEip165: '0x57b8e4f3C96180088652dc361473bB91266bb080',
},
lukso_mainnet: {
id: 'lukso',
id: 'lukso-mainnet',
name: 'lukso-mainnet',
http: {
url: 'https://rpc.mainnet.lukso.network',
url: 'https://rpc.mainnet.lukso.network/',
},
cache: {
url: 'https://erc725cache.mainnet.lukso.network/graphql',
Expand Down
70 changes: 62 additions & 8 deletions src/services/ipfs/authenticated-formdata-client.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,65 @@
import FormData from 'form-data'

import crypto from 'isomorphic-webcrypto'
import { FormDataPostHeaders } from '@/services/ipfs/formdata-base-client'
import { CustomHeaderFormDataUploader } from '@/services/ipfs/ipfs-formdata-clients'
import { PUBLIC_API_SHARED_SECRET } from '@/helpers/env'

async function sign(data: any, key: string) {
return crypto.subtle
.importKey(
'jwk', //can be "jwk" or "raw"
{
//this is an example jwk key, "raw" would be an ArrayBuffer
kty: 'oct',
k: key,
alg: 'HS256',
ext: true,
},
{
//this is the algorithm options
name: 'HMAC',
hash: { name: 'SHA-256' }, //can be "SHA-1", "SHA-256", "SHA-384", or "SHA-512"
//length: 256, //optional, if you want your key length to differ from the hash function's block length
},
true, //whether the key is extractable (i.e. can be used in exportKey)
['sign', 'verify'] //can be any combination of "sign" and "verify"
)
.then((key: any) => {
const jsonString = JSON.stringify(data)
const encodedData = new TextEncoder().encode(jsonString)
return crypto.subtle.sign(
{
name: 'HMAC',
},
key, //from generateKey or importKey above
encodedData //ArrayBuffer of data you want to sign
)
})
.then((token: any) => {
const u8 = new Uint8Array(token)
const str = String.fromCharCode.apply(
undefined,
u8 as unknown as number[]
)
return btoa(str)
})
}

/** local implementation of createToken to create a signed JWT token */
async function createToken(payload: any, key: string): Promise<string> {
const header = { typ: 'JWT', alg: 'HS256' }

const segments = [
encodeURIComponent(btoa(JSON.stringify(header))),
encodeURIComponent(btoa(JSON.stringify(payload))),
]

const footer = await sign(segments.join('.'), key)

segments.push(footer)

return segments.join('.')
}
export class AuthenticatedFormDataUploader extends CustomHeaderFormDataUploader {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async getHeaders(dataContent: FormData, meta?: FormDataPostHeaders) {
Expand All @@ -14,15 +70,13 @@ export class AuthenticatedFormDataUploader extends CustomHeaderFormDataUploader
return `ipfs://${result.IpfsHash}`
}
async getToken(): Promise<string> {
const sign = await import('@tsndr/cloudflare-worker-jwt').then(
m => m.sign || m.default?.sign
)

if (!PUBLIC_API_SHARED_SECRET) {
return ''
}
const now = Date.now()
const secret = PUBLIC_API_SHARED_SECRET
return await sign(
return await createToken(
{ iss: 'extension', iat: now / 1000, exp: (now + 120_000) / 1000 },
secret || ''
PUBLIC_API_SHARED_SECRET || ''
)
}
}
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@/*": ["src/*"]
},
"types": ["vite/client", "jest", "node", "@testing-library/jest-dom"],
"lib": ["esnext", "dom", "dom.iterable", "scripthost"]
"lib": ["esnext", "dom", "dom.iterable", "scripthost"],
"isolatedModules": true
},
"include": [
"src/**/*.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.node.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"compilerOptions": {
"composite": true,
"module": "ESNext",
"module": "esnext",
"moduleResolution": "Node",
"allowSyntheticDefaultImports": true
},
Expand Down
Loading