Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ BTC_RECEIVER_ADDRESS='tb1q9uxj8p043sjkm0qzlsys7677mv98j76k8cvgtg'
BTC_TRANSFER_AMOUNT=0.00001
#Bitcoin

#XRPl
XRP_TRANSFER_TEST_IS_ACTIVE=false
XRP_LISTENER_TEST_IS_ACTIVE=false
XRP_SENDER_PRIVATE_KEY='shV4vVLq2QZx8zopPSSp9BwaHKGan'
XRP_SENDER_ADDRESS='rMHC2kEJBYTmB8Nk37TgqV8gdxGeexpLe9'
XRP_RECEIVER_ADDRESS='r92HmWXA7dWQ6XNMMJJsbdWJfqYwLVNmGr'
XRP_TRANSFER_AMOUNT=0.001
#XRPl

#Solana
# Assets
SOL_COIN_TRANSFER_TEST_IS_ACTIVE=false
Expand Down
2 changes: 1 addition & 1 deletion packages/networks/bitcoin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
],
"author": "MultipleChain",
"license": "MIT",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/bitcoin",
"repository": {
"type": "git",
"url": "git+https://github.com/MultipleChain/js.git"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ export class TransactionListener<

if (
this.filter?.signer !== undefined &&
values.sender !== this.filter.signer.toLowerCase()
values.sender?.toLowerCase() !== this.filter.signer.toLowerCase()
) {
return
}
Expand Down
2 changes: 1 addition & 1 deletion packages/networks/boilerplate/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
],
"author": "MultipleChain",
"license": "MIT",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/boilerplate",
"repository": {
"type": "git",
"url": "git+https://github.com/MultipleChain/js.git"
Expand Down
4 changes: 2 additions & 2 deletions packages/networks/solana/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@multiplechain/solana",
"version": "0.4.15",
"version": "0.4.16",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.es.js",
Expand Down Expand Up @@ -63,7 +63,7 @@
],
"author": "MultipleChain",
"license": "MIT",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/solana",
"repository": {
"type": "git",
"url": "git+https://github.com/MultipleChain/js.git"
Expand Down
36 changes: 20 additions & 16 deletions packages/networks/solana/src/assets/Token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,23 +57,27 @@ export class Token extends Contract implements TokenInterface<TransactionSigner>
'confirmed',
programId
)
if (result === null) return null
return (this.metadata = {
name: result.name,
symbol: result.symbol,
programId: programId.toBase58(),
decimals: accountInfo.value.data.parsed.info.decimals
})
} else {
const metaplex = Metaplex.make(this.provider.web3)
const data = await metaplex.nfts().findByMint({ mintAddress: this.pubKey })
return (this.metadata = {
name: data.name,
symbol: data.symbol,
programId: programId.toBase58(),
decimals: accountInfo.value.data.parsed.info.decimals
})
if (result !== null) {
return (this.metadata = {
name: result.name,
symbol: result.symbol,
programId: programId.toBase58(),
decimals: accountInfo.value.data.parsed.info.decimals
})
}
}

const metaplex = Metaplex.make(this.provider.web3)
const data = await metaplex.nfts().findByMint({ mintAddress: this.pubKey })

if (data === null) return null

return (this.metadata = {
name: data.name,
symbol: data.symbol,
programId: programId.toBase58(),
decimals: accountInfo.value.data.parsed.info.decimals
})
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/networks/ton/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@multiplechain/ton",
"version": "0.1.0",
"version": "0.1.10",
"type": "module",
"main": "dist/index.cjs",
"module": "dist/index.es.js",
Expand Down Expand Up @@ -63,7 +63,7 @@
],
"author": "MultipleChain",
"license": "MIT",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/network-name",
"homepage": "https://github.com/MultipleChain/js/tree/master/packages/networks/ton",
"repository": {
"type": "git",
"url": "git+https://github.com/MultipleChain/js.git"
Expand Down
87 changes: 56 additions & 31 deletions packages/networks/ton/src/browser/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ import { Provider } from '../services/Provider'
import { CHAIN, type TonConnectUI } from '@tonconnect/ui'
import type { TransactionSigner } from '../services/TransactionSigner'
import { Address, Cell, type CommonMessageInfoRelaxedInternal } from '@ton/core'
import type {
WalletInterface,
WalletAdapterInterface,
WalletPlatformEnum,
TransactionId,
SignedMessage,
WalletAddress,
ConnectConfig,
UnknownConfig
import {
type WalletInterface,
type WalletAdapterInterface,
type WalletPlatformEnum,
type TransactionId,
type SignedMessage,
type WalletAddress,
type ConnectConfig,
type UnknownConfig,
ErrorTypeEnum
} from '@multiplechain/types'

type WalletAdapter = WalletAdapterInterface<Provider, TonConnectUI>

const rejectMap = (error: any, reject: (a: any) => any): any => {
console.error('MultipleChain TON Connect Error:', error)
// const errorMessage = String(error.message ?? '')
const errorMessage = String(error.message ?? '')
if (errorMessage.includes('Reject request')) {
return reject(ErrorTypeEnum.WALLET_REQUEST_REJECTED)
}
return reject(error)
}

Expand Down Expand Up @@ -107,7 +111,14 @@ export class Wallet implements WalletInterface<Provider, TonConnectUI, Transacti
resolve(await this.getAddress())
})
.catch((error) => {
rejectMap(error, reject)
const customReject = (error: any): void => {
if (error.message === ErrorTypeEnum.WALLET_REQUEST_REJECTED) {
reject(new Error(ErrorTypeEnum.WALLET_CONNECT_REJECTED))
} else {
reject(error)
}
}
rejectMap(error, customReject)
})
})
}
Expand Down Expand Up @@ -163,28 +174,42 @@ export class Wallet implements WalletInterface<Provider, TonConnectUI, Transacti
notifications: []
}
): Promise<TransactionId> {
const account = this.walletProvider.account
const data = transactionSigner.getRawData()
const info = data.info as CommonMessageInfoRelaxedInternal
const result = await this.walletProvider.sendTransaction(
{
validUntil: Math.floor(Date.now() / 1000) + 60,
from: this.getRawAddress(),
network: account?.chain,
messages: [
{
return await new Promise((resolve, reject) => {
try {
const account = this.walletProvider.account
const messages = transactionSigner.getRawData()

const tonConnectMessageFormat = []
for (const message of messages) {
const info = message.info as CommonMessageInfoRelaxedInternal
tonConnectMessageFormat.push({
address: info.dest.toString(),
amount: info.value.coins.toString(),
payload: data.body.toBoc().toString('base64')
}
]
},
modalAction
)

const messageHash = Cell.fromBase64(result.boc).hash().toString('hex')

return await this.networkProvider.findTxHashByMessageHash(messageHash)
payload: message.body.toBoc().toString('base64')
})
}

this.walletProvider
.sendTransaction(
{
validUntil: Math.floor(Date.now() / 1000) + 60,
from: this.getRawAddress(),
network: account?.chain,
messages: tonConnectMessageFormat
},
modalAction
)
.then(async (result) => {
const messageHash = Cell.fromBase64(result.boc).hash().toString('hex')
resolve(await this.networkProvider.findTxHashByMessageHash(messageHash))
})
.catch((error) => {
rejectMap(error, reject)
})
} catch (error) {
rejectMap(error, reject)
}
})
}

/**
Expand Down
20 changes: 16 additions & 4 deletions packages/networks/ton/src/browser/adapters/TonConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import type { ConnectConfig, WalletAdapterInterface } from '@multiplechain/types
export type TonConnectConfig = ConnectConfig & {
manifestUrl?: string
buttonRootId?: string
themeMode?: THEME
themeMode?: string
}

let ui: TonConnectUI
let rejectedAction: (reason?: any) => void
let connectedAction: (value: TonConnectUI | PromiseLike<TonConnectUI>) => void

const createUI = (config?: TonConnectConfig): TonConnectUI => {
Expand All @@ -20,7 +21,7 @@ const createUI = (config?: TonConnectConfig): TonConnectUI => {

ui = new TonConnectUI({
uiPreferences: {
theme: config?.themeMode ?? THEME.LIGHT
theme: config?.themeMode === 'light' ? THEME.LIGHT : THEME.DARK
},
manifestUrl: config?.manifestUrl,
buttonRootId: config?.buttonRootId
Expand All @@ -33,6 +34,12 @@ const createUI = (config?: TonConnectConfig): TonConnectUI => {
}
})

ui.onModalStateChange((state) => {
if (state.status === 'closed' && state.closeReason === 'action-cancelled') {
rejectedAction(ErrorTypeEnum.CLOSED_WALLETCONNECT_MODAL)
}
})

return ui
}

Expand All @@ -46,8 +53,12 @@ const TonConnect: WalletAdapterInterface<Provider, TonConnectUI> = {
return ui?.connected ?? false
},
disconnect: async () => {
if (ui) {
await ui.disconnect()
try {
if (ui) {
await ui.disconnect()
}
} catch (error) {
console.error(error)
}
},
connect: async (provider?: Provider, _config?: ConnectConfig) => {
Expand All @@ -67,6 +78,7 @@ const TonConnect: WalletAdapterInterface<Provider, TonConnectUI> = {
return await new Promise((resolve, reject) => {
try {
connectedAction = resolve
rejectedAction = reject
void createUI(config).openModal()
} catch (error) {
reject(error)
Expand Down
9 changes: 9 additions & 0 deletions packages/networks/ton/src/services/Provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,15 @@
})
}

/**
* Create wallet contract for version 4
* @param publicKey - Public key of the wallet
* @returns Wallet contract
*/
createWalletV4(publicKey: Buffer): WalletContractV4 {
return WalletContractV4.create({ workchain: this.workchain, publicKey })

Check warning on line 307 in packages/networks/ton/src/services/Provider.ts

View check run for this annotation

Codecov / codecov/patch

packages/networks/ton/src/services/Provider.ts#L306-L307

Added lines #L306 - L307 were not covered by tests
}

/**
* Retry the function
* @param fn - Function that will be retried
Expand Down
43 changes: 36 additions & 7 deletions packages/networks/ton/src/services/TransactionSigner.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Provider } from '../services/Provider'
import { mnemonicToPrivateKey } from '@ton/crypto'
import type { OpenedContract, WalletContractV5R1 } from '@ton/ton'
import { type Cell, SendMode, type MessageRelaxed } from '@ton/core'
import type { OpenedContract, WalletContractV4, WalletContractV5R1 } from '@ton/ton'
import type { PrivateKey, TransactionId, TransactionSignerInterface } from '@multiplechain/types'

export class TransactionSigner implements TransactionSignerInterface<MessageRelaxed, Cell> {
export class TransactionSigner implements TransactionSignerInterface<MessageRelaxed[], Cell> {
/**
* Transaction data from the blockchain network
*/
rawData: MessageRelaxed
rawData: MessageRelaxed[]

/**
* Signed transaction data
Expand All @@ -23,14 +23,14 @@
/**
* Wallet contract
*/
wallet: OpenedContract<WalletContractV5R1>
wallet: OpenedContract<WalletContractV5R1 | WalletContractV4>

/**
* @param rawData - Transaction data
* @param provider - Blockchain network provider
*/
constructor(rawData: MessageRelaxed, provider?: Provider) {
this.rawData = rawData
this.rawData = [rawData]
this.provider = provider ?? Provider.instance
}

Expand All @@ -47,7 +47,26 @@
this.signedData = this.wallet.createTransfer({
seqno,
secretKey,
messages: [this.rawData],
messages: this.rawData,
sendMode: SendMode.PAY_GAS_SEPARATELY
})
return this
}

/**
* Sign the transaction
* @param privateKey - Transaction data
* @returns Signed transaction data
*/
async signV4(privateKey: PrivateKey): Promise<this> {
const { publicKey, secretKey } = await mnemonicToPrivateKey(privateKey.split(' '))
const contract = this.provider.createWalletV4(publicKey)
this.wallet = this.provider.client1.open(contract)
const seqno = await this.wallet.getSeqno()
this.signedData = this.wallet.createTransfer({

Check warning on line 66 in packages/networks/ton/src/services/TransactionSigner.ts

View check run for this annotation

Codecov / codecov/patch

packages/networks/ton/src/services/TransactionSigner.ts#L61-L66

Added lines #L61 - L66 were not covered by tests
seqno,
secretKey,
messages: this.rawData,
sendMode: SendMode.PAY_GAS_SEPARATELY
})
return this
Expand All @@ -70,10 +89,20 @@
/**
* @returns raw transaction data
*/
getRawData(): MessageRelaxed {
getRawData(): MessageRelaxed[] {
return this.rawData
}

/**
* Add a message to the transaction
* @param message - Message data
* @returns Transaction signer
*/
addMessage(message: MessageRelaxed): this {
this.rawData.push(message)
return this

Check warning on line 103 in packages/networks/ton/src/services/TransactionSigner.ts

View check run for this annotation

Codecov / codecov/patch

packages/networks/ton/src/services/TransactionSigner.ts#L101-L103

Added lines #L101 - L103 were not covered by tests
}

/**
* @returns signed transaction data
*/
Expand Down
Loading