From a8e309d3e53f940422c303ccbc3796617294c191 Mon Sep 17 00:00:00 2001 From: Anton F Date: Mon, 11 Jul 2022 18:36:43 +0200 Subject: [PATCH 1/4] WIP new generic interface for smartcontracts of any shape and size --- .../org/ton/smartcontract/SmartContract.kt | 49 +++--- .../AuthorizedEd25519SeqnoWalletContract.kt | 97 +++++++++++ .../wallet/AuthorizedEd25519WalletContract.kt | 35 ++++ .../wallet/AuthorizedSeqnoWalletContract.kt | 96 +++++++++++ .../wallet/AuthorizedWalletContract.kt | 78 +++++++++ .../wallet/GetPublicKeyWallet.kt | 18 --- .../wallet/GetPublicKeyWalletContract.kt | 32 ++++ .../ton/smartcontract/wallet/SeqnoWallet.kt | 16 -- .../wallet/SeqnoWalletContract.kt | 28 ++++ .../smartcontract/wallet/WalletContract.kt | 150 +----------------- .../wallet/v1/AbstractAuthorizedWalletV1.kt | 9 ++ .../wallet/v1/AbstractWalletV1.kt | 11 -- .../ton/smartcontract/wallet/v1/WalletV1R1.kt | 17 +- .../ton/smartcontract/wallet/v1/WalletV1R2.kt | 18 +-- .../ton/smartcontract/wallet/v1/WalletV1R3.kt | 19 +-- .../wallet/v2/AbstractAuthorizedWalletV2.kt | 25 +++ .../wallet/v2/AbstractWalletV2.kt | 29 ---- .../ton/smartcontract/wallet/v2/WalletV2R1.kt | 19 +-- .../ton/smartcontract/wallet/v2/WalletV2R2.kt | 21 +-- .../wallet/v3/AbstractAuthorizedWalletV3.kt | 39 +++++ .../wallet/v3/AbstractWalletV3.kt | 41 ----- .../ton/smartcontract/wallet/v3/WalletV3R1.kt | 22 +-- .../ton/smartcontract/wallet/v3/WalletV3R2.kt | 23 +-- .../wallet/v4/AbstractAuthorizedWalletV4.kt | 41 +++++ .../wallet/v4/AbstractWalletV4.kt | 44 ----- .../ton/smartcontract/wallet/v4/WalletV4R2.kt | 29 ++-- 26 files changed, 569 insertions(+), 437 deletions(-) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWallet.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractAuthorizedWalletV2.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractWalletV2.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractAuthorizedWalletV3.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractWalletV3.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractAuthorizedWalletV4.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractWalletV4.kt diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/SmartContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/SmartContract.kt index 1bd814a9..1ca5c0a9 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/SmartContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/SmartContract.kt @@ -10,32 +10,43 @@ import org.ton.lite.api.liteserver.LiteServerSendMsgStatus import org.ton.tlb.TlbCodec import org.ton.tlb.storeTlb +/** + * Basic interface to any smart-contract that can be used to either deploy new contracts to the network or work with + * already deployed contracts. + * Only fields that are by definition known for all contracts are present here, more can be freely added by specific implementations + */ interface SmartContract { - val liteApi: LiteApi - val workchainId: Int - val name: String - val code: Cell - + /** + * Different workchains may define own mechanisms, therefore it is important to know workchain id. + * + * Note: This particular smart-contract interface is only valid for basic workchain (id=0) and masterchain (id=1) + */ + val workchain_id: Int + + /** + * Create initial code cell + */ + fun createCodeInit(): Cell + + /** + * Create initial data cell + */ fun createDataInit(): Cell - fun createStateInit(): StateInit = StateInit( - code, createDataInit() - ) - - fun address(stateInit: StateInit = createStateInit()): AddrStd = - address(workchainId, stateInit) - - fun createExternalInitMessage(): Message + /** + * Create state_init structure based on [createCodeInit] and [createDataInit] + */ + fun createStateInit(): StateInit = StateInit(createCodeInit(), createDataInit()) - suspend fun deploy(): LiteServerSendMsgStatus - - override fun toString(): String + /** + * Compute address of a smart-contract based on its [createStateInit] + */ + fun address(): AddrStd = address(workchain_id, createStateInit()) companion object { - private val stateInitCodec: TlbCodec by lazy { - StateInit.tlbCodec() - } + private val stateInitCodec: TlbCodec by lazy { StateInit.tlbCodec() } + /** Compute address of a smart-contract by its [workchainId] and [stateInit] */ @JvmStatic fun address(workchainId: Int, stateInit: StateInit): AddrStd { val cell = CellBuilder.createCell { diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt new file mode 100644 index 00000000..4de86789 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt @@ -0,0 +1,97 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.block.* +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.cell.exception.CellOverflowException +import org.ton.cell.storeRef +import org.ton.lite.api.LiteApi +import org.ton.tlb.constructor.AnyTlbConstructor +import org.ton.tlb.storeTlb + +/** + * Base class for almost every wallet contract out there, uses private key for authorization but also requires seqno + */ +abstract class AuthorizedEd25519SeqnoWalletContract( + private_key: PrivateKeyEd25519, + override val workchain_id: Int = 0, +) : AuthorizedEd25519WalletContract(private_key, workchain_id), AuthorizedSeqnoWalletContract { + /** + * Add seqno and sign message data + */ + open fun createMessageData(seqno: Int, builder: CellBuilder.() -> Unit = {}) = + createSignedMessageData { + storeUInt(seqno, 32) + apply(builder) + } + + /** + * Add latest seqno and sign message data + */ + suspend fun createMessageData(liteApi: LiteApi, builder: CellBuilder.() -> Unit): Cell = + createMessageData(seqno(liteApi), builder) + + override fun createExternalInitMessage(): Message { + val stateInit = createStateInit() + val ownAddress = address() + + return Message( + info = ExtInMsgInfo(ownAddress), + init = stateInit, + body = createMessageData(0) + ) + } + + override suspend fun createTransferMessage( + liteApi: LiteApi, + seqno: Int, + destination: MsgAddressInt, + amount: Coins, + payload: Cell, + bounce: Boolean, + sendMode: Int, + destinationStateInit: StateInit? + ): Message { + return Message( + info = ExtInMsgInfo(address()), + init = null, + body = createMessageData(seqno) { + storeUInt(sendMode, 8) + storeRef { + val messageRelaxed = MessageRelaxed( + info = CommonMsgInfoRelaxed.IntMsgInfoRelaxed( + ihrDisabled = true, + bounce = bounce, + bounced = false, + src = AddrNone, + dest = destination, + value = CurrencyCollection( + coins = amount + ) + ), + init = destinationStateInit, + body = payload, + storeBodyInRef = false + ) + try { + storeTlb(MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed) + } catch (e: CellOverflowException) { + storeTlb( + MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed.copy( + body = Either.of(null, payload) + ) + ) + } + } + }, + storeInitInRef = false, + storeBodyInRef = false + ) + } + + override fun createDataInit(): Cell = CellBuilder.createCell { + storeUInt(0, 32) // seqno + storeBytes(publicKey().key) // public key + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt new file mode 100644 index 00000000..6faeb071 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt @@ -0,0 +1,35 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.cell.Cell +import org.ton.cell.CellBuilder + +/** + * Most often operations on wallets are authorized using a single Ed25519 private key + */ +abstract class AuthorizedEd25519WalletContract( + private val private_key: PrivateKeyEd25519, + override val workchain_id: Int = 0, +) : AuthorizedWalletContract { + /** + * Get wallet's public key + */ + fun publicKey() = private_key.publicKey() + + /** + * Sign arbitrary cell. Use with caution + */ + fun signCell(data: Cell): ByteArray = private_key.sign(data.hash()) + + /** + * Create signed message payload from a cell builder + */ + fun createSignedMessageData(builder: CellBuilder.() -> Unit): Cell = + createSignedMessageData(CellBuilder.createCell { apply(builder) }) + + private fun createSignedMessageData(data: Cell): Cell = CellBuilder.createCell { + storeBytes(signCell(data)) + storeBits(data.bits) + storeRefs(data.refs) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt new file mode 100644 index 00000000..c62ed5d9 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt @@ -0,0 +1,96 @@ +package org.ton.smartcontract.wallet + +import org.ton.block.Coins +import org.ton.block.Message +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.lite.api.LiteApi + +/** + * Wallet contract we have a permission to perform operations on, such as transfers etc. + */ +interface AuthorizedSeqnoWalletContract : AuthorizedWalletContract, SeqnoWalletContract { + /** + * Prepare a transfer message + */ + suspend fun createTransferMessage( + liteApi: LiteApi, + seqno: Int, + destination: MsgAddressInt, + amount: Coins, + payload: Cell = Cell.of(), + bounce: Boolean, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ): Message + + override suspend fun createTransferMessage( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + payload: Cell, + bounce: Boolean, + sendMode: Int, + destinationStateInit: StateInit? + ): Message = + createTransferMessage(liteApi, seqno(liteApi), destination, amount, payload, bounce, 3, destinationStateInit) + + /** + * Perform a transfer of funds + */ + suspend fun transfer( + liteApi: LiteApi, + seqno: Int, + destination: MsgAddressInt, + amount: Coins, + payload: Cell = Cell.of(), + bounce: Boolean = true, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ) { + val message = + createTransferMessage(liteApi, seqno, destination, amount, payload, bounce, sendMode, destinationStateInit) + liteApi.sendMessage(message) + } + + /** + * Perform a transfer of funds with a text comment + */ + suspend fun transfer( + liteApi: LiteApi, + seqno: Int, + destination: MsgAddressInt, + amount: Coins, + comment: String, + bounce: Boolean = true, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ) { + transfer(liteApi, seqno, destination, amount, comment, bounce, sendMode, destinationStateInit) + } + + override suspend fun transfer( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + payload: Cell, + bounce: Boolean, + sendMode: Int, + destinationStateInit: StateInit? + ) { + transfer(liteApi, seqno(liteApi), destination, amount, payload, bounce, sendMode, destinationStateInit) + } + + override suspend fun transfer( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + comment: String, + bounce: Boolean, + sendMode: Int, + destinationStateInit: StateInit? + ) { + transfer(liteApi, seqno(liteApi), destination, amount, comment, bounce, sendMode, destinationStateInit) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt new file mode 100644 index 00000000..eae14be5 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt @@ -0,0 +1,78 @@ +package org.ton.smartcontract.wallet + +import org.ton.block.Coins +import org.ton.block.Message +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.lite.api.LiteApi + +/** + * Wallet contract we have a permission to perform operations on, such as transfers etc. + */ +interface AuthorizedWalletContract : WalletContract { + /** + * Prepare a transfer message + */ + suspend fun createTransferMessage( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + payload: Cell = Cell.of(), + bounce: Boolean = true, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ): Message + + /** + * Most of the time messages have some sort of text comment attached to them + */ + fun createCommentPayload(comment: String): Cell { + val commentBytes = comment.encodeToByteArray() + require(commentBytes.size <= 123) { TODO("comment is too long: ${commentBytes.size} bytes provided, 123 max supported") } + return CellBuilder.createCell { + storeUInt(0, 32) // op == 0 for comments + storeBytes(commentBytes) + } + } + + /** + * Perform a transfer of funds + */ + suspend fun transfer( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + payload: Cell = Cell.of(), + bounce: Boolean = true, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ) + + /** + * Perform a transfer of funds with a text comment + */ + suspend fun transfer( + liteApi: LiteApi, + destination: MsgAddressInt, + amount: Coins, + comment: String, + bounce: Boolean = true, + sendMode: Int = 3, + destinationStateInit: StateInit? = null, + ) = transfer(liteApi, destination, amount, createCommentPayload(comment), bounce, sendMode, destinationStateInit) + + /** + * Prepare an external initialization message to deploy the contract + */ + fun createExternalInitMessage(): Message + + /** + * Use [createExternalInitMessage]'s result to deploy the contract to the network + */ + suspend fun deploy(liteApi: LiteApi) { + val initMessage = createExternalInitMessage() + liteApi.sendMessage(initMessage) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWallet.kt deleted file mode 100644 index 2b0effb0..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWallet.kt +++ /dev/null @@ -1,18 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.pub.PublicKeyEd25519 -import org.ton.api.tonnode.TonNodeBlockIdExt -import org.ton.block.VmStackValue -import org.ton.lite.api.liteserver.LiteServerAccountId -import org.ton.smartcontract.SmartContract - -interface GetPublicKeyWallet : SmartContract { - suspend fun getPublicKey(): PublicKeyEd25519 = getPublicKey(liteApi.getMasterchainInfo().last) - - suspend fun getPublicKey(blockIdExt: TonNodeBlockIdExt): PublicKeyEd25519 { - val liteServerAccountId = LiteServerAccountId(address()) - val result = liteApi.runSmcMethod(4, blockIdExt, liteServerAccountId, "get_public_key") - val rawPublicKey = (result.first() as VmStackValue.Int).value.toByteArray() - return PublicKeyEd25519(rawPublicKey) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt new file mode 100644 index 00000000..1d24d7fb --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt @@ -0,0 +1,32 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pub.PublicKeyEd25519 +import org.ton.api.tonnode.TonNodeBlockIdExt +import org.ton.block.VmStackValue +import org.ton.lite.api.LiteApi +import org.ton.lite.api.liteserver.LiteServerAccountId + +/** + * Wallets generally implement a method to fetch their public key. + * This can be used to verify whether a signed message was produced by the owner of a specific wallet + */ +interface GetPublicKeyWalletContract : WalletContract { + /** + * Get most recently public key + */ + suspend fun getPublicKey(liteApi: LiteApi): PublicKeyEd25519 = + getPublicKey(liteApi, liteApi.getMasterchainInfo().last) + + /** + * Get public key as of [referenceBlockId] + */ + suspend fun getPublicKey(liteApi: LiteApi, referenceBlockId: TonNodeBlockIdExt): PublicKeyEd25519 { + val liteServerAccountId = LiteServerAccountId(address()) + val result = liteApi.runSmcMethod(4, referenceBlockId, liteServerAccountId, "get_public_key") + require(result.exitCode == 0) { "failed to run smc method `get_public_key` with exit code ${result.exitCode}" } + require(result.resultValues().orEmpty().size == 1 && (result.first() !is VmStackValue.Int)) + { "failed to get proper result for `get_public_key` smc method" } + val rawPublicKey = (result.first() as VmStackValue.Int).value.toByteArray() + return PublicKeyEd25519(rawPublicKey) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt deleted file mode 100644 index ceab6dcf..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.tonnode.TonNodeBlockIdExt -import org.ton.block.VmStackValue -import org.ton.lite.api.liteserver.LiteServerAccountId -import org.ton.smartcontract.SmartContract - -interface SeqnoWallet : SmartContract { - suspend fun seqno(): Int = seqno(liteApi.getMasterchainInfo().last) - - suspend fun seqno(blockIdExt: TonNodeBlockIdExt): Int { - val liteServerAccountId = LiteServerAccountId(address()) - val result = liteApi.runSmcMethod(4, blockIdExt, liteServerAccountId, "seqno") - return (result.first() as VmStackValue.TinyInt).value.toInt() - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt new file mode 100644 index 00000000..1f630ea3 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt @@ -0,0 +1,28 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.tonnode.TonNodeBlockIdExt +import org.ton.block.VmStackValue +import org.ton.lite.api.LiteApi +import org.ton.lite.api.liteserver.LiteServerAccountId + +/** + * Most wallets implement sequence number (seqno) in order to circumvent replay attacks + */ +interface SeqnoWalletContract : WalletContract { + /** + * Get most recent seqno + */ + suspend fun seqno(liteApi: LiteApi): Int = seqno(liteApi, liteApi.getMasterchainInfo().last) + + /** + * Get seqno value as of [referenceBlockId] + */ + suspend fun seqno(liteApi: LiteApi, referenceBlockId: TonNodeBlockIdExt): Int { + val liteServerAccountId = LiteServerAccountId(address()) + val result = liteApi.runSmcMethod(4, referenceBlockId, liteServerAccountId, "seqno") + require(result.exitCode == 0) { "failed to run smc method `seqno` with exit code ${result.exitCode}" } + require(result.resultValues().orEmpty().size == 1 && (result.first() !is VmStackValue.TinyInt)) + { "failed to get proper result for `seqno` smc method" } + return (result.first() as VmStackValue.TinyInt).value.toInt() + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt index 5c10c723..b08bb250 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt @@ -1,150 +1,8 @@ package org.ton.smartcontract.wallet -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.block.* -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.cell.exception.CellOverflowException -import org.ton.cell.storeRef -import org.ton.lite.api.LiteApi -import org.ton.lite.api.liteserver.LiteServerSendMsgStatus -import org.ton.logger.Logger import org.ton.smartcontract.SmartContract -import org.ton.tlb.constructor.AnyTlbConstructor -import org.ton.tlb.storeTlb -abstract class WalletContract( - override val liteApi: LiteApi, - val privateKey: PrivateKeyEd25519, - override val workchainId: Int = 0 -) : SmartContract { - val logger: Logger by lazy { - Logger.println(name, Logger.Level.DEBUG) - } - - override suspend fun deploy(): LiteServerSendMsgStatus { - val initMessage = createExternalInitMessage() - logger.info { "Deploy: $initMessage" } - return liteApi.sendMessage(initMessage) - } - - suspend fun transfer( - dest: MsgAddressInt, - bounce: Boolean, - coins: Coins, - seqno: Int, - comment: String? - ): LiteServerSendMsgStatus = transfer(dest, bounce, coins, seqno, createCommentPayload(comment)) - - suspend fun transfer( - dest: MsgAddressInt, - bounce: Boolean, - coins: Coins, - seqno: Int, - payload: Cell, - destinationStateInit: StateInit? = null, - ): LiteServerSendMsgStatus { - val transferMessage = createTransferMessage(dest, bounce, coins, seqno, payload, destinationStateInit = destinationStateInit) - logger.info { "Transfer: $transferMessage" } - return liteApi.sendMessage(transferMessage) - } - - override fun createDataInit(): Cell = CellBuilder.createCell { - storeUInt(0, 32) // seqno - storeBytes(privateKey.publicKey().key) - } - - open fun createSigningMessage(seqno: Int, builder: CellBuilder.() -> Unit = {}): Cell = CellBuilder.createCell { - storeUInt(seqno, 32) - apply(builder) - } - - override fun createExternalInitMessage(): Message { - val stateInit = createStateInit() - val dest = address(stateInit) - val signingMessage = createSigningMessage(0) - val signature = privateKey.sign(signingMessage.hash()) - val body = CellBuilder.createCell { - storeBytes(signature) - storeBits(signingMessage.bits) - storeRefs(signingMessage.refs) - } - val info = ExtInMsgInfo(dest) - return Message( - info, - stateInit to null, - body to null - ) - } - - fun createTransferMessage( - dest: MsgAddressInt, - bounce: Boolean, - amount: Coins, - seqno: Int, - payload: Cell, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ): Message { - val stateInit = createStateInit() - val address = address(stateInit) - val info = ExtInMsgInfo(address) - val signingMessage = createSigningMessage(seqno) { - storeUInt(sendMode, 8) - storeRef { - val messageRelaxed = MessageRelaxed( - info = CommonMsgInfoRelaxed.IntMsgInfoRelaxed( - ihrDisabled = true, - bounce = bounce, - bounced = false, - src = AddrNone, - dest = dest, - value = CurrencyCollection( - coins = amount - ) - ), - init = destinationStateInit, - body = payload, - storeBodyInRef = false - ) - try { - storeTlb(MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed) - } catch (e: CellOverflowException) { - storeTlb( - MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed.copy( - body = Either.of(null, payload) - ) - ) - } - } - } - val signature = privateKey.sign(signingMessage.hash()) - val body = CellBuilder.createCell { - storeBytes(signature) - storeBits(signingMessage.bits) - storeRefs(signingMessage.refs) - } - return Message( - info = info, - init = null, - body = body, - storeInitInRef = false, - storeBodyInRef = false - ) - } - - fun createCommentPayload(comment: String? = null): Cell { - return if (comment == null) { - Cell.of() - } else { - val commentBytes = comment.encodeToByteArray() - require(commentBytes.size <= 123) { TODO("Commentaries with more than 123 bytes not supported yet. Provided: ${commentBytes.size}") } - CellBuilder.createCell { - storeUInt(0, 32) - storeBytes(commentBytes) - } - } - } - - override fun toString(): String = name -} +/** + * Base interface for all wallet contracts, any externally-controlled contract whose main purpose is sending and receiving funds. + */ +interface WalletContract : SmartContract diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt new file mode 100644 index 00000000..21b1b220 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt @@ -0,0 +1,9 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.smartcontract.wallet.AuthorizedEd25519SeqnoWalletContract + +abstract class AbstractAuthorizedWalletV1( + private_key: PrivateKeyEd25519, + override val workchain_id: Int = 0, +) : AuthorizedEd25519SeqnoWalletContract(private_key, workchain_id) diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt deleted file mode 100644 index ce680f4d..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt +++ /dev/null @@ -1,11 +0,0 @@ -package org.ton.smartcontract.wallet.v1 - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.WalletContract - -abstract class AbstractWalletV1( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0 -) : WalletContract(liteApi, privateKey, workchainId) diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt index 0d92fb6d..a5cd8282 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt @@ -2,7 +2,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi /** * Wallet v1 revision 1 @@ -10,15 +9,9 @@ import org.ton.lite.api.LiteApi * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/c2da007f4065e2520e0d948b146e0fb12fa75751/crypto/smartcont/new-wallet.fif) */ class WalletV1R1( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0 -) : AbstractWalletV1(liteApi, privateKey, workchainId) { - override val name: String = "v1r1" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, +) : AbstractAuthorizedWalletV1(private_key, workchain_id) { + override fun createCodeInit(): Cell = + Cell("FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt index 6fc6485a..f997b870 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt @@ -2,8 +2,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.SeqnoWallet /** * Wallet v1 revision 2 @@ -13,15 +11,9 @@ import org.ton.smartcontract.wallet.SeqnoWallet * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/47814dca3d4d7d253f0dcbb2ef176f45aafc6871/crypto/smartcont/new-wallet.fif) */ class WalletV1R2( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0 -) : AbstractWalletV1(liteApi, privateKey, workchainId), SeqnoWallet { - override val name: String = "v1r2" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, +) : AbstractAuthorizedWalletV1(private_key, workchain_id) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt index d0391c31..77a81bc1 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt @@ -2,9 +2,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.GetPublicKeyWallet -import org.ton.smartcontract.wallet.SeqnoWallet /** * Wallet v1 revision 3 @@ -14,15 +11,9 @@ import org.ton.smartcontract.wallet.SeqnoWallet * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif) */ class WalletV1R3( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0 -) : AbstractWalletV1(liteApi, privateKey, workchainId), SeqnoWallet, GetPublicKeyWallet { - override val name: String = "v1r3" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, +) : AbstractAuthorizedWalletV1(private_key, workchain_id) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractAuthorizedWalletV2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractAuthorizedWalletV2.kt new file mode 100644 index 00000000..81d9fbfa --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractAuthorizedWalletV2.kt @@ -0,0 +1,25 @@ +package org.ton.smartcontract.wallet.v2 + +import kotlinx.datetime.Clock +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.bitstring.BitString +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.smartcontract.wallet.AuthorizedEd25519SeqnoWalletContract + +abstract class AbstractAuthorizedWalletV2( + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + private val timeout: Long = 60 +) : AuthorizedEd25519SeqnoWalletContract(private_key, workchain_id) { + override fun createMessageData(seqno: Int, builder: CellBuilder.() -> Unit): Cell = + super.createMessageData(seqno) { + if (seqno == 0) { + storeBits(BitString("FFFFFFFF")) + } else { + val now = Clock.System.now().toEpochMilliseconds() / 1000 + storeUInt(now + timeout, 32) + } + apply(builder) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractWalletV2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractWalletV2.kt deleted file mode 100644 index 61a0c1b0..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/AbstractWalletV2.kt +++ /dev/null @@ -1,29 +0,0 @@ -package org.ton.smartcontract.wallet.v2 - -import kotlinx.datetime.Clock -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.bitstring.BitString -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.SeqnoWallet -import org.ton.smartcontract.wallet.WalletContract - -abstract class AbstractWalletV2( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - private val timeout: Long = 60 -) : WalletContract(liteApi, privateKey, workchainId), SeqnoWallet { - - override fun createSigningMessage(seqno: Int, builder: CellBuilder.() -> Unit): Cell = CellBuilder.createCell { - storeUInt(seqno, 32) - if (seqno == 0) { - storeBits(BitString("FFFFFFFF")) - } else { - val now = Clock.System.now().toEpochMilliseconds() / 1000 - storeUInt(now + timeout, 32) - } - apply(builder) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R1.kt index b0eb696a..1e599c18 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R1.kt @@ -2,7 +2,6 @@ package org.ton.smartcontract.wallet.v2 import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi /** * Wallet v2 revision 1 @@ -12,16 +11,10 @@ import org.ton.lite.api.LiteApi * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/fd7a8de9708c9ece8d802890519735b55bc99a8e/crypto/smartcont/new-wallet-v2.fif) */ class WalletV2R1( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - timeout: Long = 60 -) : AbstractWalletV2(liteApi, privateKey, workchainId, timeout) { - override val name: String = "v2R1" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F2608308D71820D31FD31F01F823BBF263ED44D0D31FD3FFD15131BAF2A103F901541042F910F2A2F800029320D74A96D307D402FB00E8D1A4C8CB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + timeout: Long = 60, +) : AbstractAuthorizedWalletV2(private_key, workchain_id, timeout) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F2608308D71820D31FD31F01F823BBF263ED44D0D31FD3FFD15131BAF2A103F901541042F910F2A2F800029320D74A96D307D402FB00E8D1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R2.kt index 0565eb80..86499d79 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v2/WalletV2R2.kt @@ -2,8 +2,6 @@ package org.ton.smartcontract.wallet.v2 import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.GetPublicKeyWallet /** * Wallet v2 revision 2 @@ -13,16 +11,11 @@ import org.ton.smartcontract.wallet.GetPublicKeyWallet * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet-v2.fif) */ class WalletV2R2( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - timeout: Long = 60 -) : AbstractWalletV2(liteApi, privateKey, workchainId, timeout), GetPublicKeyWallet { - override val name: String = "v2R2" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F2608308D71820D31FD31F01F823BBF263ED44D0D31FD3FFD15131BAF2A103F901541042F910F2A2F800029320D74A96D307D402FB00E8D1A4C8CB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + timeout: Long = 60, +) : AbstractAuthorizedWalletV2(private_key, workchain_id, timeout) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F2608308D71820D31FD31F01F823BBF263ED44D0D31FD3FFD15131BAF2A103F901541042F910F2A2F800029320D74A96D307D402FB00E8D1A4C8CB1FCBFFC9ED54") } + diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractAuthorizedWalletV3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractAuthorizedWalletV3.kt new file mode 100644 index 00000000..18a1a11b --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractAuthorizedWalletV3.kt @@ -0,0 +1,39 @@ +package org.ton.smartcontract.wallet.v3 + +import kotlinx.datetime.Clock +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.bitstring.BitString +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.smartcontract.wallet.AuthorizedEd25519SeqnoWalletContract + +abstract class AbstractAuthorizedWalletV3( + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + val subwallet_id: Int = DEFAULT_WALLET_ID + workchain_id, + private val timeout: Long = 60 +) : AuthorizedEd25519SeqnoWalletContract(private_key, workchain_id) { + override fun createDataInit(): Cell = CellBuilder.createCell { + storeUInt(0, 32) // seqno + storeUInt(subwallet_id, 32) + storeBytes(publicKey().key) + } + + override fun createMessageData(seqno: Int, builder: CellBuilder.() -> Unit): Cell = + createSignedMessageData { + storeUInt(subwallet_id, 32) + if (seqno == 0) { + storeBits(BitString("FFFFFFFF")) + } else { + val now = Clock.System.now().toEpochMilliseconds() / 1000 + storeUInt(now + timeout, 32) + } + storeUInt(seqno, 32) + apply(builder) + } + + companion object { + const val DEFAULT_WALLET_ID = 698983191 + } +} + diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractWalletV3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractWalletV3.kt deleted file mode 100644 index 8613bc04..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/AbstractWalletV3.kt +++ /dev/null @@ -1,41 +0,0 @@ -package org.ton.smartcontract.wallet.v3 - -import kotlinx.datetime.Clock -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.bitstring.BitString -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.SeqnoWallet -import org.ton.smartcontract.wallet.WalletContract - -abstract class AbstractWalletV3( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - val subwalletId: Int = DEFAULT_WALLET_ID + workchainId, - private val timeout: Long = 60 -) : WalletContract(liteApi, privateKey, workchainId), SeqnoWallet { - - override fun createDataInit(): Cell = CellBuilder.createCell { - storeUInt(0, 32) // seqno - storeUInt(subwalletId, 32) - storeBytes(privateKey.publicKey().key) - } - - override fun createSigningMessage(seqno: Int, builder: CellBuilder.() -> Unit): Cell = CellBuilder.createCell { - storeUInt(subwalletId, 32) - if (seqno == 0) { - storeBits(BitString("FFFFFFFF")) - } else { - val now = Clock.System.now().toEpochMilliseconds() / 1000 - storeUInt(now + timeout, 32) - } - storeUInt(seqno, 32) - apply(builder) - } - - companion object { - const val DEFAULT_WALLET_ID = 698983191 - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R1.kt index 414c7b34..920c8f53 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R1.kt @@ -1,8 +1,8 @@ package org.ton.smartcontract.wallet.v3 +import io.ktor.http.* import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi /** * Wallet v3 revision 1 @@ -13,17 +13,11 @@ import org.ton.lite.api.LiteApi * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/3002321eb779e9936243e3b5f00be7579fb07654/crypto/smartcont/new-wallet-v3.fif) */ class WalletV3R1( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - subwalletId: Int = DEFAULT_WALLET_ID + workchainId, - timeout: Long = 60 -) : AbstractWalletV3(liteApi, privateKey, workchainId, subwalletId, timeout) { - override val name: String = "v3r1" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F2608308D71820D31FD31FD31FF82313BBF263ED44D0D31FD31FD3FFD15132BAF2A15144BAF2A204F901541055F910F2A3F8009320D74A96D307D402FB00E8D101A4C8CB1FCB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + subwallet_id: Int = DEFAULT_PORT + workchain_id, + timeout: Long = 60, +) : AbstractAuthorizedWalletV3(private_key, workchain_id, subwallet_id, timeout) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F2608308D71820D31FD31FD31FF82313BBF263ED44D0D31FD31FD3FFD15132BAF2A15144BAF2A204F901541055F910F2A3F8009320D74A96D307D402FB00E8D101A4C8CB1FCB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R2.kt index 48477d37..9116b8b9 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v3/WalletV3R2.kt @@ -1,9 +1,8 @@ package org.ton.smartcontract.wallet.v3 +import io.ktor.http.* import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.GetPublicKeyWallet /** * Wallet v3 revision 1 @@ -13,17 +12,11 @@ import org.ton.smartcontract.wallet.GetPublicKeyWallet * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/3002321eb779e9936243e3b5f00be7579fb07654/crypto/smartcont/new-wallet-v3.fif) */ class WalletV3R2( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - subwalletId: Int = DEFAULT_WALLET_ID + workchainId, - timeout: Long = 60 -) : AbstractWalletV3(liteApi, privateKey, workchainId, subwalletId, timeout), GetPublicKeyWallet { - override val name: String = "v3r2" - override val code: Cell = CODE - - companion object { - val CODE: Cell = - Cell("FF0020DD2082014C97BA218201339CBAB19F71B0ED44D0D31FD31F31D70BFFE304E0A4F2608308D71820D31FD31FD31FF82313BBF263ED44D0D31FD31FD3FFD15132BAF2A15144BAF2A204F901541055F910F2A3F8009320D74A96D307D402FB00E8D101A4C8CB1FCB1FCBFFC9ED54") - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + subwallet_id: Int = DEFAULT_PORT + workchain_id, + timeout: Long = 60, +) : AbstractAuthorizedWalletV3(private_key, workchain_id, subwallet_id, timeout) { + override fun createCodeInit(): Cell = + Cell("FF0020DD2082014C97BA218201339CBAB19F71B0ED44D0D31FD31F31D70BFFE304E0A4F2608308D71820D31FD31FD31FF82313BBF263ED44D0D31FD31FD3FFD15132BAF2A15144BAF2A204F901541055F910F2A3F8009320D74A96D307D402FB00E8D101A4C8CB1FCB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractAuthorizedWalletV4.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractAuthorizedWalletV4.kt new file mode 100644 index 00000000..f32f6841 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractAuthorizedWalletV4.kt @@ -0,0 +1,41 @@ +package org.ton.smartcontract.wallet.v4 + +import kotlinx.datetime.Clock +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.bitstring.BitString +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.smartcontract.wallet.AuthorizedEd25519SeqnoWalletContract + +abstract class AbstractAuthorizedWalletV4( + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + val subwallet_id: Int = DEFAULT_WALLET_ID + workchain_id, + private val timeout: Long = 60 +) : AuthorizedEd25519SeqnoWalletContract(private_key, workchain_id) { + override fun createDataInit(): Cell = CellBuilder.createCell { + storeUInt(0, 32) // seqno + storeUInt(subwallet_id, 32) + storeBytes(publicKey().key) + storeUInt(0, 1) // plugins dict empty + } + + override fun createMessageData(seqno: Int, builder: CellBuilder.() -> Unit): Cell = + createSignedMessageData { + storeUInt(subwallet_id, 32) + if (seqno == 0) { + storeBits(BitString("FFFFFFFF")) + } else { + val now = Clock.System.now().toEpochMilliseconds() / 1000 + storeUInt(now + timeout, 32) + } + storeUInt(seqno, 32) + storeUInt(0, 8) // op + apply(builder) + } + + companion object { + const val DEFAULT_WALLET_ID = 698983191 + } +} + diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractWalletV4.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractWalletV4.kt deleted file mode 100644 index a084675b..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/AbstractWalletV4.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.ton.smartcontract.wallet.v4 - -import kotlinx.datetime.Clock -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.bitstring.BitString -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.GetPublicKeyWallet -import org.ton.smartcontract.wallet.SeqnoWallet -import org.ton.smartcontract.wallet.WalletContract - -abstract class AbstractWalletV4( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - val subwalletId: Int = DEFAULT_WALLET_ID + workchainId, - private val timeout: Long = 60 -) : WalletContract(liteApi, privateKey, workchainId), SeqnoWallet, GetPublicKeyWallet { - - override fun createDataInit(): Cell = CellBuilder.createCell { - storeUInt(0, 32) // seqno - storeUInt(subwalletId, 32) - storeBytes(privateKey.publicKey().key) - storeUInt(0, 1) // plugins dict empty - } - - override fun createSigningMessage(seqno: Int, builder: CellBuilder.() -> Unit): Cell = CellBuilder.createCell { - storeUInt(subwalletId, 32) - if (seqno == 0) { - storeBits(BitString("FFFFFFFF")) - } else { - val now = Clock.System.now().toEpochMilliseconds() / 1000 - storeUInt(now + timeout, 32) - } - storeUInt(seqno, 32) - storeUInt(0, 8) // op - apply(builder) - } - - companion object { - const val DEFAULT_WALLET_ID = 698983191 - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/WalletV4R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/WalletV4R2.kt index 1010ec03..3b09d385 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/WalletV4R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v4/WalletV4R2.kt @@ -1,30 +1,23 @@ package org.ton.smartcontract.wallet.v4 +import io.ktor.http.* import org.ton.api.pk.PrivateKeyEd25519 import org.ton.boc.BagOfCells import org.ton.cell.Cell import org.ton.crypto.hex -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.GetPublicKeyWallet /** * Wallet v4 revision 1 */ class WalletV4R2( - liteApi: LiteApi, - privateKey: PrivateKeyEd25519, - workchainId: Int = 0, - subwalletId: Int = DEFAULT_WALLET_ID + workchainId, - timeout: Long = 60 -) : AbstractWalletV4(liteApi, privateKey, workchainId, subwalletId, timeout), GetPublicKeyWallet { - override val name: String = "v4r2" - override val code: Cell = CODE - - companion object { - val CODE: Cell = BagOfCells( - hex( - "B5EE9C72410214010002D4000114FF00F4A413F4BCF2C80B010201200203020148040504F8F28308D71820D31FD31FD31F02F823BBF264ED44D0D31FD31FD3FFF404D15143BAF2A15151BAF2A205F901541064F910F2A3F80024A4C8CB1F5240CB1F5230CBFF5210F400C9ED54F80F01D30721C0009F6C519320D74A96D307D402FB00E830E021C001E30021C002E30001C0039130E30D03A4C8CB1F12CB1FCBFF1011121302E6D001D0D3032171B0925F04E022D749C120925F04E002D31F218210706C7567BD22821064737472BDB0925F05E003FA403020FA4401C8CA07CBFFC9D0ED44D0810140D721F404305C810108F40A6FA131B3925F07E005D33FC8258210706C7567BA923830E30D03821064737472BA925F06E30D06070201200809007801FA00F40430F8276F2230500AA121BEF2E0508210706C7567831EB17080185004CB0526CF1658FA0219F400CB6917CB1F5260CB3F20C98040FB0006008A5004810108F45930ED44D0810140D720C801CF16F400C9ED540172B08E23821064737472831EB17080185005CB055003CF1623FA0213CB6ACB1FCB3FC98040FB00925F03E20201200A0B0059BD242B6F6A2684080A06B90FA0218470D4080847A4937D29910CE6903E9FF9837812801B7810148987159F31840201580C0D0011B8C97ED44D0D70B1F8003DB29DFB513420405035C87D010C00B23281F2FFF274006040423D029BE84C600201200E0F0019ADCE76A26840206B90EB85FFC00019AF1DF6A26840106B90EB858FC0006ED207FA00D4D422F90005C8CA0715CBFFC9D077748018C8CB05CB0222CF165005FA0214CB6B12CCCCC973FB00C84014810108F451F2A7020070810108D718FA00D33FC8542047810108F451F2A782106E6F746570748018C8CB05CB025006CF165004FA0214CB6A12CB1FCB3FC973FB0002006C810108D718FA00D33F305224810108F459F2A782106473747270748018C8CB05CB025005CF165003FA0213CB6ACB1F12CB3FC973FB00000AF400C9ED54696225E5" - ) - ).first() - } + private_key: PrivateKeyEd25519, + workchain_id: Int = 0, + subwallet_id: Int = DEFAULT_PORT + workchain_id, + timeout: Long = 60, +) : AbstractAuthorizedWalletV4(private_key, workchain_id, subwallet_id, timeout) { + override fun createCodeInit(): Cell = BagOfCells( + hex( + "B5EE9C72410214010002D4000114FF00F4A413F4BCF2C80B010201200203020148040504F8F28308D71820D31FD31FD31F02F823BBF264ED44D0D31FD31FD3FFF404D15143BAF2A15151BAF2A205F901541064F910F2A3F80024A4C8CB1F5240CB1F5230CBFF5210F400C9ED54F80F01D30721C0009F6C519320D74A96D307D402FB00E830E021C001E30021C002E30001C0039130E30D03A4C8CB1F12CB1FCBFF1011121302E6D001D0D3032171B0925F04E022D749C120925F04E002D31F218210706C7567BD22821064737472BDB0925F05E003FA403020FA4401C8CA07CBFFC9D0ED44D0810140D721F404305C810108F40A6FA131B3925F07E005D33FC8258210706C7567BA923830E30D03821064737472BA925F06E30D06070201200809007801FA00F40430F8276F2230500AA121BEF2E0508210706C7567831EB17080185004CB0526CF1658FA0219F400CB6917CB1F5260CB3F20C98040FB0006008A5004810108F45930ED44D0810140D720C801CF16F400C9ED540172B08E23821064737472831EB17080185005CB055003CF1623FA0213CB6ACB1FCB3FC98040FB00925F03E20201200A0B0059BD242B6F6A2684080A06B90FA0218470D4080847A4937D29910CE6903E9FF9837812801B7810148987159F31840201580C0D0011B8C97ED44D0D70B1F8003DB29DFB513420405035C87D010C00B23281F2FFF274006040423D029BE84C600201200E0F0019ADCE76A26840206B90EB85FFC00019AF1DF6A26840106B90EB858FC0006ED207FA00D4D422F90005C8CA0715CBFFC9D077748018C8CB05CB0222CF165005FA0214CB6B12CCCCC973FB00C84014810108F451F2A7020070810108D718FA00D33FC8542047810108F451F2A782106E6F746570748018C8CB05CB025006CF165004FA0214CB6A12CB1FCB3FC973FB0002006C810108D718FA00D33F305224810108F459F2A782106473747270748018C8CB05CB025005CF165003FA0213CB6ACB1F12CB3FC973FB00000AF400C9ED54696225E5" + ) + ).first() } From 52e965464d23206849977a0440bf60c2b0f7bb3c Mon Sep 17 00:00:00 2001 From: Anton F Date: Tue, 12 Jul 2022 14:23:57 +0200 Subject: [PATCH 2/4] I am definetely onto something --- ...tractEd25519SeqnoTransferMessageBuilder.kt | 30 ++++++ ...tractEd25519SeqnoTransferWalletContract.kt | 21 ++++ .../AuthorizedEd25519SeqnoWalletContract.kt | 97 ------------------- .../wallet/AuthorizedEd25519WalletContract.kt | 35 ------- .../wallet/AuthorizedSeqnoWalletContract.kt | 96 ------------------ .../wallet/AuthorizedWalletContract.kt | 78 --------------- .../wallet/Ed25519TransferMessageBuilder.kt | 17 ++++ .../wallet/Ed25519TransferWalletContract.kt | 13 +++ .../wallet/GetPublicKeyWalletContract.kt | 32 ------ .../wallet/SeqnoTransferMessageBuilder.kt | 13 +++ .../wallet/SeqnoTransferWalletContract.kt | 7 ++ .../wallet/TransferMessageBuilder.kt | 59 +++++++++++ .../wallet/TransferWalletContract.kt | 13 +++ .../wallet/v1/AbstractAuthorizedWalletV1.kt | 9 -- .../wallet/v1/AbstractWalletV1.kt | 19 ++++ .../ton/smartcontract/wallet/v1/WalletV1R1.kt | 2 +- .../ton/smartcontract/wallet/v1/WalletV1R2.kt | 2 +- .../ton/smartcontract/wallet/v1/WalletV1R3.kt | 2 +- .../v1/WalletV1TransferMessageBuilder.kt | 33 +++++++ 19 files changed, 228 insertions(+), 350 deletions(-) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt new file mode 100644 index 00000000..473e487b --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt @@ -0,0 +1,30 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.block.Coins +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.lite.api.LiteApi + +abstract class AbstractEd25519SeqnoTransferMessageBuilder( + private val private_key: PrivateKeyEd25519, + override val liteApi: LiteApi, + override val source: MsgAddressInt, + override var seqno: Int, + override var payload: Cell, + override var bounce: Boolean, + override var sendMode: Int, + override var destinationStateInit: StateInit? +) : Ed25519TransferMessageBuilder, SeqnoTransferMessageBuilder { + override lateinit var destination: MsgAddressInt + override lateinit var amount: Coins + + override fun signCell(data: Cell): ByteArray = private_key.sign(data.hash()) + + override fun buildData(builder: CellBuilder.() -> Unit): Cell = + super.buildData { + super.buildData(builder) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt new file mode 100644 index 00000000..ecf98ddd --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt @@ -0,0 +1,21 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.api.pub.PublicKeyEd25519 +import org.ton.cell.Cell +import org.ton.cell.CellBuilder + +/** + * Base class for almost every wallet contract out there, uses private key for authorization but also requires seqno + */ +abstract class AbstractEd25519SeqnoTransferWalletContract( + private val private_key: PrivateKeyEd25519, + override val workchain_id: Int = 0, +) : Ed25519TransferWalletContract, SeqnoTransferWalletContract { + override fun publicKey(): PublicKeyEd25519 = private_key.publicKey() + + override fun createDataInit(): Cell = CellBuilder.createCell { + storeUInt(0, 32) // seqno + storeBytes(publicKey().key) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt deleted file mode 100644 index 4de86789..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519SeqnoWalletContract.kt +++ /dev/null @@ -1,97 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.block.* -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.cell.exception.CellOverflowException -import org.ton.cell.storeRef -import org.ton.lite.api.LiteApi -import org.ton.tlb.constructor.AnyTlbConstructor -import org.ton.tlb.storeTlb - -/** - * Base class for almost every wallet contract out there, uses private key for authorization but also requires seqno - */ -abstract class AuthorizedEd25519SeqnoWalletContract( - private_key: PrivateKeyEd25519, - override val workchain_id: Int = 0, -) : AuthorizedEd25519WalletContract(private_key, workchain_id), AuthorizedSeqnoWalletContract { - /** - * Add seqno and sign message data - */ - open fun createMessageData(seqno: Int, builder: CellBuilder.() -> Unit = {}) = - createSignedMessageData { - storeUInt(seqno, 32) - apply(builder) - } - - /** - * Add latest seqno and sign message data - */ - suspend fun createMessageData(liteApi: LiteApi, builder: CellBuilder.() -> Unit): Cell = - createMessageData(seqno(liteApi), builder) - - override fun createExternalInitMessage(): Message { - val stateInit = createStateInit() - val ownAddress = address() - - return Message( - info = ExtInMsgInfo(ownAddress), - init = stateInit, - body = createMessageData(0) - ) - } - - override suspend fun createTransferMessage( - liteApi: LiteApi, - seqno: Int, - destination: MsgAddressInt, - amount: Coins, - payload: Cell, - bounce: Boolean, - sendMode: Int, - destinationStateInit: StateInit? - ): Message { - return Message( - info = ExtInMsgInfo(address()), - init = null, - body = createMessageData(seqno) { - storeUInt(sendMode, 8) - storeRef { - val messageRelaxed = MessageRelaxed( - info = CommonMsgInfoRelaxed.IntMsgInfoRelaxed( - ihrDisabled = true, - bounce = bounce, - bounced = false, - src = AddrNone, - dest = destination, - value = CurrencyCollection( - coins = amount - ) - ), - init = destinationStateInit, - body = payload, - storeBodyInRef = false - ) - try { - storeTlb(MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed) - } catch (e: CellOverflowException) { - storeTlb( - MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed.copy( - body = Either.of(null, payload) - ) - ) - } - } - }, - storeInitInRef = false, - storeBodyInRef = false - ) - } - - override fun createDataInit(): Cell = CellBuilder.createCell { - storeUInt(0, 32) // seqno - storeBytes(publicKey().key) // public key - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt deleted file mode 100644 index 6faeb071..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedEd25519WalletContract.kt +++ /dev/null @@ -1,35 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.cell.Cell -import org.ton.cell.CellBuilder - -/** - * Most often operations on wallets are authorized using a single Ed25519 private key - */ -abstract class AuthorizedEd25519WalletContract( - private val private_key: PrivateKeyEd25519, - override val workchain_id: Int = 0, -) : AuthorizedWalletContract { - /** - * Get wallet's public key - */ - fun publicKey() = private_key.publicKey() - - /** - * Sign arbitrary cell. Use with caution - */ - fun signCell(data: Cell): ByteArray = private_key.sign(data.hash()) - - /** - * Create signed message payload from a cell builder - */ - fun createSignedMessageData(builder: CellBuilder.() -> Unit): Cell = - createSignedMessageData(CellBuilder.createCell { apply(builder) }) - - private fun createSignedMessageData(data: Cell): Cell = CellBuilder.createCell { - storeBytes(signCell(data)) - storeBits(data.bits) - storeRefs(data.refs) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt deleted file mode 100644 index c62ed5d9..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedSeqnoWalletContract.kt +++ /dev/null @@ -1,96 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.block.Coins -import org.ton.block.Message -import org.ton.block.MsgAddressInt -import org.ton.block.StateInit -import org.ton.cell.Cell -import org.ton.lite.api.LiteApi - -/** - * Wallet contract we have a permission to perform operations on, such as transfers etc. - */ -interface AuthorizedSeqnoWalletContract : AuthorizedWalletContract, SeqnoWalletContract { - /** - * Prepare a transfer message - */ - suspend fun createTransferMessage( - liteApi: LiteApi, - seqno: Int, - destination: MsgAddressInt, - amount: Coins, - payload: Cell = Cell.of(), - bounce: Boolean, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ): Message - - override suspend fun createTransferMessage( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - payload: Cell, - bounce: Boolean, - sendMode: Int, - destinationStateInit: StateInit? - ): Message = - createTransferMessage(liteApi, seqno(liteApi), destination, amount, payload, bounce, 3, destinationStateInit) - - /** - * Perform a transfer of funds - */ - suspend fun transfer( - liteApi: LiteApi, - seqno: Int, - destination: MsgAddressInt, - amount: Coins, - payload: Cell = Cell.of(), - bounce: Boolean = true, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ) { - val message = - createTransferMessage(liteApi, seqno, destination, amount, payload, bounce, sendMode, destinationStateInit) - liteApi.sendMessage(message) - } - - /** - * Perform a transfer of funds with a text comment - */ - suspend fun transfer( - liteApi: LiteApi, - seqno: Int, - destination: MsgAddressInt, - amount: Coins, - comment: String, - bounce: Boolean = true, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ) { - transfer(liteApi, seqno, destination, amount, comment, bounce, sendMode, destinationStateInit) - } - - override suspend fun transfer( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - payload: Cell, - bounce: Boolean, - sendMode: Int, - destinationStateInit: StateInit? - ) { - transfer(liteApi, seqno(liteApi), destination, amount, payload, bounce, sendMode, destinationStateInit) - } - - override suspend fun transfer( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - comment: String, - bounce: Boolean, - sendMode: Int, - destinationStateInit: StateInit? - ) { - transfer(liteApi, seqno(liteApi), destination, amount, comment, bounce, sendMode, destinationStateInit) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt deleted file mode 100644 index eae14be5..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AuthorizedWalletContract.kt +++ /dev/null @@ -1,78 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.block.Coins -import org.ton.block.Message -import org.ton.block.MsgAddressInt -import org.ton.block.StateInit -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.lite.api.LiteApi - -/** - * Wallet contract we have a permission to perform operations on, such as transfers etc. - */ -interface AuthorizedWalletContract : WalletContract { - /** - * Prepare a transfer message - */ - suspend fun createTransferMessage( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - payload: Cell = Cell.of(), - bounce: Boolean = true, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ): Message - - /** - * Most of the time messages have some sort of text comment attached to them - */ - fun createCommentPayload(comment: String): Cell { - val commentBytes = comment.encodeToByteArray() - require(commentBytes.size <= 123) { TODO("comment is too long: ${commentBytes.size} bytes provided, 123 max supported") } - return CellBuilder.createCell { - storeUInt(0, 32) // op == 0 for comments - storeBytes(commentBytes) - } - } - - /** - * Perform a transfer of funds - */ - suspend fun transfer( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - payload: Cell = Cell.of(), - bounce: Boolean = true, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ) - - /** - * Perform a transfer of funds with a text comment - */ - suspend fun transfer( - liteApi: LiteApi, - destination: MsgAddressInt, - amount: Coins, - comment: String, - bounce: Boolean = true, - sendMode: Int = 3, - destinationStateInit: StateInit? = null, - ) = transfer(liteApi, destination, amount, createCommentPayload(comment), bounce, sendMode, destinationStateInit) - - /** - * Prepare an external initialization message to deploy the contract - */ - fun createExternalInitMessage(): Message - - /** - * Use [createExternalInitMessage]'s result to deploy the contract to the network - */ - suspend fun deploy(liteApi: LiteApi) { - val initMessage = createExternalInitMessage() - liteApi.sendMessage(initMessage) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt new file mode 100644 index 00000000..17b566a1 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt @@ -0,0 +1,17 @@ +package org.ton.smartcontract.wallet + +import org.ton.cell.Cell +import org.ton.cell.CellBuilder + +interface Ed25519TransferMessageBuilder : TransferMessageBuilder { + fun signCell(data: Cell): ByteArray + + override fun buildData(builder: CellBuilder.() -> Unit): Cell { + val data = CellBuilder.createCell { apply(builder) } + return super.buildData { + storeBytes(signCell(data)) + storeBits(data.bits) + storeRefs(data.refs) + } + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt new file mode 100644 index 00000000..a0d1b6e2 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt @@ -0,0 +1,13 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pub.PublicKeyEd25519 + +/** + * Most often operations on wallets are authorized using a single Ed25519 private key + */ +interface Ed25519TransferWalletContract : TransferWalletContract { + /** + * Get wallet's public key + */ + fun publicKey(): PublicKeyEd25519 +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt deleted file mode 100644 index 1d24d7fb..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/GetPublicKeyWalletContract.kt +++ /dev/null @@ -1,32 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.pub.PublicKeyEd25519 -import org.ton.api.tonnode.TonNodeBlockIdExt -import org.ton.block.VmStackValue -import org.ton.lite.api.LiteApi -import org.ton.lite.api.liteserver.LiteServerAccountId - -/** - * Wallets generally implement a method to fetch their public key. - * This can be used to verify whether a signed message was produced by the owner of a specific wallet - */ -interface GetPublicKeyWalletContract : WalletContract { - /** - * Get most recently public key - */ - suspend fun getPublicKey(liteApi: LiteApi): PublicKeyEd25519 = - getPublicKey(liteApi, liteApi.getMasterchainInfo().last) - - /** - * Get public key as of [referenceBlockId] - */ - suspend fun getPublicKey(liteApi: LiteApi, referenceBlockId: TonNodeBlockIdExt): PublicKeyEd25519 { - val liteServerAccountId = LiteServerAccountId(address()) - val result = liteApi.runSmcMethod(4, referenceBlockId, liteServerAccountId, "get_public_key") - require(result.exitCode == 0) { "failed to run smc method `get_public_key` with exit code ${result.exitCode}" } - require(result.resultValues().orEmpty().size == 1 && (result.first() !is VmStackValue.Int)) - { "failed to get proper result for `get_public_key` smc method" } - val rawPublicKey = (result.first() as VmStackValue.Int).value.toByteArray() - return PublicKeyEd25519(rawPublicKey) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt new file mode 100644 index 00000000..f7e0d266 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt @@ -0,0 +1,13 @@ +package org.ton.smartcontract.wallet + +import org.ton.cell.Cell +import org.ton.cell.CellBuilder + +interface SeqnoTransferMessageBuilder : TransferMessageBuilder { + var seqno: Int + + override fun buildData(builder: CellBuilder.() -> Unit): Cell = super.buildData { + storeUInt(seqno, 32) + apply(builder) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt new file mode 100644 index 00000000..28e8b845 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt @@ -0,0 +1,7 @@ +package org.ton.smartcontract.wallet + +/** + * A wallet which requires you to supply seqno in order to + */ +interface SeqnoTransferWalletContract : TransferWalletContract, + SeqnoWalletContract diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt new file mode 100644 index 00000000..40103255 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt @@ -0,0 +1,59 @@ +package org.ton.smartcontract.wallet + +import org.ton.block.* +import org.ton.cell.Cell +import org.ton.cell.CellBuilder +import org.ton.cell.exception.CellOverflowException +import org.ton.cell.storeRef +import org.ton.lite.api.LiteApi +import org.ton.tlb.constructor.AnyTlbConstructor +import org.ton.tlb.storeTlb + +interface TransferMessageBuilder { + val liteApi: LiteApi + val source: MsgAddressInt + var destination: MsgAddressInt + var amount: Coins + var payload: Cell + var bounce: Boolean + var sendMode: Int + var destinationStateInit: StateInit? + + fun buildData(builder: CellBuilder.() -> Unit = {}): Cell = CellBuilder.createCell { apply(builder) } + + fun build(): Message = Message( + info = ExtInMsgInfo(source), + init = null, + body = buildData { + storeUInt(sendMode, 8) + storeRef { + val messageRelaxed = MessageRelaxed( + info = CommonMsgInfoRelaxed.IntMsgInfoRelaxed( + ihrDisabled = true, + bounce = bounce, + bounced = false, + src = AddrNone, + dest = destination, + value = CurrencyCollection( + coins = amount + ) + ), + init = destinationStateInit, + body = payload, + storeBodyInRef = false + ) + try { + storeTlb(MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed) + } catch (e: CellOverflowException) { + storeTlb( + MessageRelaxed.tlbCodec(AnyTlbConstructor), messageRelaxed.copy( + body = Either.of(null, payload) + ) + ) + } + } + }, + storeInitInRef = false, + storeBodyInRef = false + ) +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt new file mode 100644 index 00000000..269a17a2 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt @@ -0,0 +1,13 @@ +package org.ton.smartcontract.wallet + +import org.ton.lite.api.LiteApi + +/** + * Wallet contract we have a permission to perform operations on, such as transfers etc. + */ +interface TransferWalletContract : WalletContract { + /** + * Perform a transfer of funds + */ + suspend fun transfer(liteApi: LiteApi, builder: TMB.() -> Unit) +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt deleted file mode 100644 index 21b1b220..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractAuthorizedWalletV1.kt +++ /dev/null @@ -1,9 +0,0 @@ -package org.ton.smartcontract.wallet.v1 - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.smartcontract.wallet.AuthorizedEd25519SeqnoWalletContract - -abstract class AbstractAuthorizedWalletV1( - private_key: PrivateKeyEd25519, - override val workchain_id: Int = 0, -) : AuthorizedEd25519SeqnoWalletContract(private_key, workchain_id) diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt new file mode 100644 index 00000000..a2d0097c --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt @@ -0,0 +1,19 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.AbstractEd25519SeqnoTransferWalletContract + +abstract class AbstractWalletV1( + private val private_key: PrivateKeyEd25519, + override val workchain_id: Int = 0, +) : AbstractEd25519SeqnoTransferWalletContract(private_key, workchain_id) { + override suspend fun transfer(liteApi: LiteApi, builder: WalletV1TransferMessageBuilder.() -> Unit) { + WalletV1TransferMessageBuilder( + private_key = private_key, + liteApi = liteApi, + source = address(), + seqno = seqno(liteApi), + ).apply(builder) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt index a5cd8282..4b5cb4c1 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt @@ -11,7 +11,7 @@ import org.ton.cell.Cell class WalletV1R1( private_key: PrivateKeyEd25519, workchain_id: Int = 0, -) : AbstractAuthorizedWalletV1(private_key, workchain_id) { +) : AbstractWalletV1(private_key, workchain_id) { override fun createCodeInit(): Cell = Cell("FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt index f997b870..55659a69 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt @@ -13,7 +13,7 @@ import org.ton.cell.Cell class WalletV1R2( private_key: PrivateKeyEd25519, workchain_id: Int = 0, -) : AbstractAuthorizedWalletV1(private_key, workchain_id) { +) : AbstractWalletV1(private_key, workchain_id) { override fun createCodeInit(): Cell = Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt index 77a81bc1..617b7528 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt @@ -13,7 +13,7 @@ import org.ton.cell.Cell class WalletV1R3( private_key: PrivateKeyEd25519, workchain_id: Int = 0, -) : AbstractAuthorizedWalletV1(private_key, workchain_id) { +) : AbstractWalletV1(private_key, workchain_id) { override fun createCodeInit(): Cell = Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt new file mode 100644 index 00000000..93e20cda --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt @@ -0,0 +1,33 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.block.Coins +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.AbstractEd25519SeqnoTransferMessageBuilder + +class WalletV1TransferMessageBuilder( + private_key: PrivateKeyEd25519, + override val liteApi: LiteApi, + override val source: MsgAddressInt, + override var seqno: Int, + override var payload: Cell = Cell.of(), + override var bounce: Boolean = true, + override var sendMode: Int = 3, + override var destinationStateInit: StateInit? = null, +) : + AbstractEd25519SeqnoTransferMessageBuilder( + private_key, + liteApi, + source, + seqno, + payload, + bounce, + sendMode, + destinationStateInit + ) { + override lateinit var destination: MsgAddressInt + override lateinit var amount: Coins +} From c4607b5acd8f5ca2b5ddb0107863d2b7949f454f Mon Sep 17 00:00:00 2001 From: Anton F Date: Tue, 12 Jul 2022 15:12:41 +0200 Subject: [PATCH 3/4] Shit's bussin fr fr --- ...tractEd25519SeqnoTransferMessageBuilder.kt | 30 ---------------- ...lletContract.kt => BasicTransferWallet.kt} | 10 +++--- .../wallet/SeqnoTransferWallet.kt | 9 +++++ .../wallet/SeqnoTransferWalletContract.kt | 7 ---- ...{SeqnoWalletContract.kt => SeqnoWallet.kt} | 2 +- .../wallet/SignedSeqnoTransferWallet.kt | 9 +++++ ...letContract.kt => SignedTransferWallet.kt} | 3 +- .../ton/smartcontract/wallet/SignedWallet.kt | 31 +++++++++++++++++ ...ferWalletContract.kt => TransferWallet.kt} | 5 +-- .../wallet/{WalletContract.kt => Wallet.kt} | 7 +++- .../wallet/builder/BasicTransferBuilder.kt | 24 +++++++++++++ .../SeqnoTransferBuilder.kt} | 4 +-- .../builder/SignedSeqnoTransferBuilder.kt | 11 ++++++ .../SignedTransferBuilder.kt} | 4 +-- .../TransferBuilder.kt} | 34 +++++++++++++------ .../wallet/v1/AbstractWalletV1.kt | 19 ----------- .../wallet/v1/TransferWalletV1R1.kt | 18 ++++++++++ .../wallet/v1/TransferWalletV1R2.kt | 18 ++++++++++ .../wallet/v1/TransferWalletV1R3.kt | 18 ++++++++++ .../wallet/v1/V1TransferBuilder.kt | 33 ++++++++++++++++++ .../ton/smartcontract/wallet/v1/WalletV1R1.kt | 13 ++++--- .../ton/smartcontract/wallet/v1/WalletV1R2.kt | 13 ++++--- .../ton/smartcontract/wallet/v1/WalletV1R3.kt | 13 ++++--- .../v1/WalletV1TransferMessageBuilder.kt | 33 ------------------ .../wallet/v1/WalletV1R3Example.kt | 8 ++--- .../smartcontract/wallet/v1/WalletV1R3Test.kt | 16 ++++----- 26 files changed, 250 insertions(+), 142 deletions(-) delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{AbstractEd25519SeqnoTransferWalletContract.kt => BasicTransferWallet.kt} (55%) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWallet.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{SeqnoWalletContract.kt => SeqnoWallet.kt} (95%) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedSeqnoTransferWallet.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{Ed25519TransferWalletContract.kt => SignedTransferWallet.kt} (63%) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedWallet.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{TransferWalletContract.kt => TransferWallet.kt} (54%) rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{WalletContract.kt => Wallet.kt} (57%) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/BasicTransferBuilder.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{SeqnoTransferMessageBuilder.kt => builder/SeqnoTransferBuilder.kt} (68%) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{Ed25519TransferMessageBuilder.kt => builder/SignedTransferBuilder.kt} (78%) rename ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/{TransferMessageBuilder.kt => builder/TransferBuilder.kt} (66%) delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferBuilder.kt delete mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt deleted file mode 100644 index 473e487b..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferMessageBuilder.kt +++ /dev/null @@ -1,30 +0,0 @@ -package org.ton.smartcontract.wallet - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.block.Coins -import org.ton.block.MsgAddressInt -import org.ton.block.StateInit -import org.ton.cell.Cell -import org.ton.cell.CellBuilder -import org.ton.lite.api.LiteApi - -abstract class AbstractEd25519SeqnoTransferMessageBuilder( - private val private_key: PrivateKeyEd25519, - override val liteApi: LiteApi, - override val source: MsgAddressInt, - override var seqno: Int, - override var payload: Cell, - override var bounce: Boolean, - override var sendMode: Int, - override var destinationStateInit: StateInit? -) : Ed25519TransferMessageBuilder, SeqnoTransferMessageBuilder { - override lateinit var destination: MsgAddressInt - override lateinit var amount: Coins - - override fun signCell(data: Cell): ByteArray = private_key.sign(data.hash()) - - override fun buildData(builder: CellBuilder.() -> Unit): Cell = - super.buildData { - super.buildData(builder) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/BasicTransferWallet.kt similarity index 55% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/BasicTransferWallet.kt index ecf98ddd..574a4307 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/AbstractEd25519SeqnoTransferWalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/BasicTransferWallet.kt @@ -4,14 +4,12 @@ import org.ton.api.pk.PrivateKeyEd25519 import org.ton.api.pub.PublicKeyEd25519 import org.ton.cell.Cell import org.ton.cell.CellBuilder +import org.ton.smartcontract.wallet.builder.SignedSeqnoTransferBuilder -/** - * Base class for almost every wallet contract out there, uses private key for authorization but also requires seqno - */ -abstract class AbstractEd25519SeqnoTransferWalletContract( +abstract class BasicTransferWallet( private val private_key: PrivateKeyEd25519, - override val workchain_id: Int = 0, -) : Ed25519TransferWalletContract, SeqnoTransferWalletContract { + override val workchain_id: Int = 0 +) : SignedSeqnoTransferWallet { override fun publicKey(): PublicKeyEd25519 = private_key.publicKey() override fun createDataInit(): Cell = CellBuilder.createCell { diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWallet.kt new file mode 100644 index 00000000..74514a66 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWallet.kt @@ -0,0 +1,9 @@ +package org.ton.smartcontract.wallet + +import org.ton.smartcontract.wallet.builder.SeqnoTransferBuilder + +/** + * A wallet which requires you to supply seqno in order to + */ +interface SeqnoTransferWallet : TransferWallet, + SeqnoWallet diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt deleted file mode 100644 index 28e8b845..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferWalletContract.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.ton.smartcontract.wallet - -/** - * A wallet which requires you to supply seqno in order to - */ -interface SeqnoTransferWalletContract : TransferWalletContract, - SeqnoWalletContract diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt similarity index 95% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt index 1f630ea3..9e26a533 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoWallet.kt @@ -8,7 +8,7 @@ import org.ton.lite.api.liteserver.LiteServerAccountId /** * Most wallets implement sequence number (seqno) in order to circumvent replay attacks */ -interface SeqnoWalletContract : WalletContract { +interface SeqnoWallet : Wallet { /** * Get most recent seqno */ diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedSeqnoTransferWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedSeqnoTransferWallet.kt new file mode 100644 index 00000000..69b42b19 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedSeqnoTransferWallet.kt @@ -0,0 +1,9 @@ +package org.ton.smartcontract.wallet + +import org.ton.smartcontract.wallet.builder.SignedSeqnoTransferBuilder + +/** + * Base class for almost every wallet contract out there, uses private key for authorization but also requires seqno + */ +interface SignedSeqnoTransferWallet : SignedTransferWallet, + SeqnoTransferWallet diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedTransferWallet.kt similarity index 63% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedTransferWallet.kt index a0d1b6e2..b72ab68e 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferWalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedTransferWallet.kt @@ -1,11 +1,12 @@ package org.ton.smartcontract.wallet import org.ton.api.pub.PublicKeyEd25519 +import org.ton.smartcontract.wallet.builder.SignedTransferBuilder /** * Most often operations on wallets are authorized using a single Ed25519 private key */ -interface Ed25519TransferWalletContract : TransferWalletContract { +interface SignedTransferWallet : TransferWallet { /** * Get wallet's public key */ diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedWallet.kt new file mode 100644 index 00000000..e333ce52 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SignedWallet.kt @@ -0,0 +1,31 @@ +package org.ton.smartcontract.wallet + +import org.ton.api.pub.PublicKeyEd25519 +import org.ton.api.tonnode.TonNodeBlockIdExt +import org.ton.block.VmStackValue +import org.ton.lite.api.LiteApi +import org.ton.lite.api.liteserver.LiteServerAccountId + +/** + * Most wallets implement method `get_public_key` + */ +interface SignedWallet : Wallet { + /** + * Get most recent public_key + */ + suspend fun getPublicKey(liteApi: LiteApi): PublicKeyEd25519 = + getPublicKey(liteApi, liteApi.getMasterchainInfo().last) + + /** + * Get public key value as of [referenceBlockId] + */ + suspend fun getPublicKey(liteApi: LiteApi, referenceBlockId: TonNodeBlockIdExt): PublicKeyEd25519 { + val liteServerAccountId = LiteServerAccountId(address()) + val result = liteApi.runSmcMethod(4, referenceBlockId, liteServerAccountId, "get_public_key") + require(result.exitCode == 0) { "failed to run smc method `get_public_key` with exit code ${result.exitCode}" } + require(result.resultValues().orEmpty().size == 1 && (result.first() !is VmStackValue.Int)) + { "failed to get proper result for `get_public_key` smc method" } + val rawPublicKey = (result.first() as VmStackValue.Int).value.toByteArray() + return PublicKeyEd25519(rawPublicKey) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt similarity index 54% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt index 269a17a2..43b1c1f9 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt @@ -1,13 +1,14 @@ package org.ton.smartcontract.wallet import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.builder.TransferBuilder /** * Wallet contract we have a permission to perform operations on, such as transfers etc. */ -interface TransferWalletContract : WalletContract { +interface TransferWallet : Wallet { /** * Perform a transfer of funds */ - suspend fun transfer(liteApi: LiteApi, builder: TMB.() -> Unit) + suspend fun transfer(lite_api: LiteApi, builder: TMB.() -> Unit) } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Wallet.kt similarity index 57% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Wallet.kt index b08bb250..19cf9b9a 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/WalletContract.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Wallet.kt @@ -1,8 +1,13 @@ package org.ton.smartcontract.wallet +import org.ton.cell.Cell import org.ton.smartcontract.SmartContract /** * Base interface for all wallet contracts, any externally-controlled contract whose main purpose is sending and receiving funds. */ -interface WalletContract : SmartContract +interface Wallet : SmartContract { + override fun createDataInit(): Cell { + throw Exception("cannot create data cell") + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/BasicTransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/BasicTransferBuilder.kt new file mode 100644 index 00000000..63a6f47b --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/BasicTransferBuilder.kt @@ -0,0 +1,24 @@ +package org.ton.smartcontract.wallet.builder + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.block.Coins +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.lite.api.LiteApi + +abstract class BasicTransferBuilder( + private val private_key: PrivateKeyEd25519, + override val lite_api: LiteApi, + override val src: MsgAddressInt, + override var seqno: Int, + override var payload: Cell = Cell.of(), + override var bounce: Boolean = true, + override var send_mode: Int = 3, + override var dest_state_init: StateInit? = null, +) : SignedSeqnoTransferBuilder { + override lateinit var dest: MsgAddressInt + override lateinit var amount: Coins + + override fun signCell(data: Cell): ByteArray = private_key.sign(data.hash()) +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt similarity index 68% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt index f7e0d266..568bc6c3 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/SeqnoTransferMessageBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt @@ -1,9 +1,9 @@ -package org.ton.smartcontract.wallet +package org.ton.smartcontract.wallet.builder import org.ton.cell.Cell import org.ton.cell.CellBuilder -interface SeqnoTransferMessageBuilder : TransferMessageBuilder { +interface SeqnoTransferBuilder : TransferBuilder { var seqno: Int override fun buildData(builder: CellBuilder.() -> Unit): Cell = super.buildData { diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt new file mode 100644 index 00000000..ebf6ce76 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt @@ -0,0 +1,11 @@ +package org.ton.smartcontract.wallet.builder + +import org.ton.cell.Cell +import org.ton.cell.CellBuilder + +interface SignedSeqnoTransferBuilder : SignedTransferBuilder, SeqnoTransferBuilder { + override fun buildData(builder: CellBuilder.() -> Unit): Cell = + super.buildData { + super.buildData(builder) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt similarity index 78% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt index 17b566a1..ca915ac8 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/Ed25519TransferMessageBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt @@ -1,9 +1,9 @@ -package org.ton.smartcontract.wallet +package org.ton.smartcontract.wallet.builder import org.ton.cell.Cell import org.ton.cell.CellBuilder -interface Ed25519TransferMessageBuilder : TransferMessageBuilder { +interface SignedTransferBuilder : TransferBuilder { fun signCell(data: Cell): ByteArray override fun buildData(builder: CellBuilder.() -> Unit): Cell { diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt similarity index 66% rename from ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt rename to ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt index 40103255..fe4111d2 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferMessageBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt @@ -1,4 +1,4 @@ -package org.ton.smartcontract.wallet +package org.ton.smartcontract.wallet.builder import org.ton.block.* import org.ton.cell.Cell @@ -9,23 +9,35 @@ import org.ton.lite.api.LiteApi import org.ton.tlb.constructor.AnyTlbConstructor import org.ton.tlb.storeTlb -interface TransferMessageBuilder { - val liteApi: LiteApi - val source: MsgAddressInt - var destination: MsgAddressInt +interface TransferBuilder { + val lite_api: LiteApi + val src: MsgAddressInt + + var dest: MsgAddressInt var amount: Coins var payload: Cell var bounce: Boolean - var sendMode: Int - var destinationStateInit: StateInit? + var send_mode: Int + var dest_state_init: StateInit? + + var comment: String + get() = TODO() + set(value) { + val commentBytes = comment.encodeToByteArray() + require(commentBytes.size <= 123) { TODO("comment is too long: ${commentBytes.size} bytes provided, 123 max supported") } + payload = CellBuilder.createCell { + storeUInt(0, 32) // op == 0 for comments + storeBytes(commentBytes) + } + } fun buildData(builder: CellBuilder.() -> Unit = {}): Cell = CellBuilder.createCell { apply(builder) } fun build(): Message = Message( - info = ExtInMsgInfo(source), + info = ExtInMsgInfo(src), init = null, body = buildData { - storeUInt(sendMode, 8) + storeUInt(send_mode, 8) storeRef { val messageRelaxed = MessageRelaxed( info = CommonMsgInfoRelaxed.IntMsgInfoRelaxed( @@ -33,12 +45,12 @@ interface TransferMessageBuilder { bounce = bounce, bounced = false, src = AddrNone, - dest = destination, + dest = dest, value = CurrencyCollection( coins = amount ) ), - init = destinationStateInit, + init = dest_state_init, body = payload, storeBodyInRef = false ) diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt deleted file mode 100644 index a2d0097c..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/AbstractWalletV1.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.ton.smartcontract.wallet.v1 - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.AbstractEd25519SeqnoTransferWalletContract - -abstract class AbstractWalletV1( - private val private_key: PrivateKeyEd25519, - override val workchain_id: Int = 0, -) : AbstractEd25519SeqnoTransferWalletContract(private_key, workchain_id) { - override suspend fun transfer(liteApi: LiteApi, builder: WalletV1TransferMessageBuilder.() -> Unit) { - WalletV1TransferMessageBuilder( - private_key = private_key, - liteApi = liteApi, - source = address(), - seqno = seqno(liteApi), - ).apply(builder) - } -} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt new file mode 100644 index 00000000..2b257410 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt @@ -0,0 +1,18 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.BasicTransferWallet + +class TransferWalletV1R1(private val private_key: PrivateKeyEd25519) : + BasicTransferWallet(private_key), + WalletV1R1 { + override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { + V1TransferBuilder( + private_key = private_key, + lite_api = lite_api, + src = address(), + seqno = seqno(lite_api) + ) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt new file mode 100644 index 00000000..c93fcb9c --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt @@ -0,0 +1,18 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.BasicTransferWallet + +class TransferWalletV1R2(private val private_key: PrivateKeyEd25519) : + BasicTransferWallet(private_key), + WalletV1R2 { + override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { + V1TransferBuilder( + private_key = private_key, + lite_api = lite_api, + src = address(), + seqno = seqno(lite_api) + ) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt new file mode 100644 index 00000000..6da2d15e --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt @@ -0,0 +1,18 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.BasicTransferWallet + +class TransferWalletV1R3(private val private_key: PrivateKeyEd25519) : + BasicTransferWallet(private_key), + WalletV1R3 { + override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { + V1TransferBuilder( + private_key = private_key, + lite_api = lite_api, + src = address(), + seqno = seqno(lite_api) + ) + } +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferBuilder.kt new file mode 100644 index 00000000..2a2e9823 --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferBuilder.kt @@ -0,0 +1,33 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.block.Coins +import org.ton.block.MsgAddressInt +import org.ton.block.StateInit +import org.ton.cell.Cell +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.builder.BasicTransferBuilder + +class V1TransferBuilder( + private_key: PrivateKeyEd25519, + override val lite_api: LiteApi, + override val src: MsgAddressInt, + override var seqno: Int = 0, + override var payload: Cell = Cell.of(), + override var bounce: Boolean = true, + override var send_mode: Int = 3, + override var dest_state_init: StateInit? = null, +) : + BasicTransferBuilder( + private_key, + lite_api, + src, + seqno, + payload, + bounce, + send_mode, + dest_state_init + ) { + override lateinit var dest: MsgAddressInt + override lateinit var amount: Coins +} diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt index 4b5cb4c1..7db7d358 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R1.kt @@ -1,17 +1,20 @@ package org.ton.smartcontract.wallet.v1 -import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell +import org.ton.smartcontract.wallet.SeqnoWallet +import org.ton.smartcontract.wallet.SignedWallet +import org.ton.smartcontract.wallet.Wallet /** * Wallet v1 revision 1 * * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/c2da007f4065e2520e0d948b146e0fb12fa75751/crypto/smartcont/new-wallet.fif) */ -class WalletV1R1( - private_key: PrivateKeyEd25519, - workchain_id: Int = 0, -) : AbstractWalletV1(private_key, workchain_id) { +interface WalletV1R1 : Wallet, SeqnoWallet, SignedWallet { override fun createCodeInit(): Cell = Cell("FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } + +private class WalletV1R1Impl( + override val workchain_id: Int = 0 +) : WalletV1R1 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt index 55659a69..cadbc643 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R2.kt @@ -1,7 +1,9 @@ package org.ton.smartcontract.wallet.v1 -import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell +import org.ton.smartcontract.wallet.SeqnoWallet +import org.ton.smartcontract.wallet.SignedWallet +import org.ton.smartcontract.wallet.Wallet /** * Wallet v1 revision 2 @@ -10,10 +12,11 @@ import org.ton.cell.Cell * * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/47814dca3d4d7d253f0dcbb2ef176f45aafc6871/crypto/smartcont/new-wallet.fif) */ -class WalletV1R2( - private_key: PrivateKeyEd25519, - workchain_id: Int = 0, -) : AbstractWalletV1(private_key, workchain_id) { +interface WalletV1R2 : Wallet, SeqnoWallet, SignedWallet { override fun createCodeInit(): Cell = Cell("FF0020DD2082014C97BA9730ED44D0D70B1FE0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } + +private class WalletV1R2Impl( + override val workchain_id: Int = 0 +) : WalletV1R2 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt index 617b7528..f817f382 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3.kt @@ -1,7 +1,9 @@ package org.ton.smartcontract.wallet.v1 -import org.ton.api.pk.PrivateKeyEd25519 import org.ton.cell.Cell +import org.ton.smartcontract.wallet.SeqnoWallet +import org.ton.smartcontract.wallet.SignedWallet +import org.ton.smartcontract.wallet.Wallet /** * Wallet v1 revision 3 @@ -10,10 +12,11 @@ import org.ton.cell.Cell * * [Fift-ASM source-code](https://github.com/ton-blockchain/ton/blob/master/crypto/smartcont/new-wallet.fif) */ -class WalletV1R3( - private_key: PrivateKeyEd25519, - workchain_id: Int = 0, -) : AbstractWalletV1(private_key, workchain_id) { +interface WalletV1R3 : Wallet, SeqnoWallet, SignedWallet { override fun createCodeInit(): Cell = Cell("FF0020DD2082014C97BA218201339CBAB19C71B0ED44D0D31FD70BFFE304E0A4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54") } + +private class WalletV1R3Impl( + override val workchain_id: Int = 0 +) : WalletV1R3 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt deleted file mode 100644 index 93e20cda..00000000 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/WalletV1TransferMessageBuilder.kt +++ /dev/null @@ -1,33 +0,0 @@ -package org.ton.smartcontract.wallet.v1 - -import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.block.Coins -import org.ton.block.MsgAddressInt -import org.ton.block.StateInit -import org.ton.cell.Cell -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.AbstractEd25519SeqnoTransferMessageBuilder - -class WalletV1TransferMessageBuilder( - private_key: PrivateKeyEd25519, - override val liteApi: LiteApi, - override val source: MsgAddressInt, - override var seqno: Int, - override var payload: Cell = Cell.of(), - override var bounce: Boolean = true, - override var sendMode: Int = 3, - override var destinationStateInit: StateInit? = null, -) : - AbstractEd25519SeqnoTransferMessageBuilder( - private_key, - liteApi, - source, - seqno, - payload, - bounce, - sendMode, - destinationStateInit - ) { - override lateinit var destination: MsgAddressInt - override lateinit var amount: Coins -} diff --git a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Example.kt b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Example.kt index cda92802..ea6919dc 100644 --- a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Example.kt +++ b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Example.kt @@ -18,16 +18,16 @@ private fun liteClient() = LiteClient( suspend fun main() { val liteClient = liteClient() - val wallet = WalletV1R3(liteClient, privateKey) + val wallet = TransferWalletV1R3(privateKey) val address = wallet.address() println("Source wallet address = ${address.toString(userFriendly = false)}") println("Non-bounceable address (for init only): ${address.toString(bounceable = false, testOnly = true)}") println("Bounceable address (for later access): ${address.toString(bounceable = true, testOnly = true)}") - println("Corresponding public key is ${hex(wallet.privateKey.publicKey().key).uppercase()}") + println("Corresponding public key is ${hex(wallet.publicKey().key).uppercase()}") liteClient.connect() val block = liteClient.getMasterchainInfo().last - println("seqno: ${wallet.seqno(block)}") - println("get_public_key: ${wallet.getPublicKey(block)}") + println("seqno: ${wallet.seqno(liteClient, block)}") + println("get_public_key: ${wallet.getPublicKey(liteClient, block)}") } diff --git a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt index 9115b789..221e3a8f 100644 --- a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt +++ b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt @@ -29,7 +29,7 @@ class WalletV1R3Test { logger = PrintLnLogger("TON SimpleWalletR3", Logger.Level.DEBUG) ) - private fun wallet() = WalletV1R3(liteClient(), privateKey) + private fun wallet() = TransferWalletV1R3(privateKey) @Test fun `test private key`() { @@ -116,13 +116,13 @@ class WalletV1R3Test { assertContentEquals(expected, actual) } - private fun WalletV1R3.exampleTransferMessage(comment: String) = createTransferMessage( - dest = MsgAddressInt.parse("kQDzHsXMkamiJeqCLcrNDUuyBn78Jr7NUcx075WhEfqIPpwm"), - bounce = true, - amount = Coins.of(1), - seqno = 1, - payload = createCommentPayload(comment) - ) + private fun V1TransferBuilder.exampleTransferMessage(text: String) = this.apply { + dest = MsgAddressInt.parse("kQDzHsXMkamiJeqCLcrNDUuyBn78Jr7NUcx075WhEfqIPpwm") + bounce = true + amount = Coins.of(1) + seqno = 1 + comment = text + }.build() @Test fun `test transfer message with 'Hello TON' comment`() { From b90ec790c1b748aaa3c05e6553c1a566e42632db Mon Sep 17 00:00:00 2001 From: Anton F Date: Tue, 12 Jul 2022 15:29:26 +0200 Subject: [PATCH 4/4] Yeah its p good --- .../ton/smartcontract/wallet/TransferWallet.kt | 7 ++++++- .../wallet/builder/SeqnoTransferBuilder.kt | 2 +- .../wallet/builder/SignedSeqnoTransferBuilder.kt | 6 +++--- .../wallet/builder/SignedTransferBuilder.kt | 4 ++-- .../wallet/builder/TransferBuilder.kt | 6 +++--- .../wallet/v1/TransferWalletV1R1.kt | 16 ++-------------- .../wallet/v1/TransferWalletV1R2.kt | 16 ++-------------- .../wallet/v1/TransferWalletV1R3.kt | 16 ++-------------- .../smartcontract/wallet/v1/V1TransferWallet.kt | 16 ++++++++++++++++ .../smartcontract/wallet/v1/WalletV1R3Test.kt | 9 ++++++--- 10 files changed, 43 insertions(+), 55 deletions(-) create mode 100644 ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferWallet.kt diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt index 43b1c1f9..02606bce 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/TransferWallet.kt @@ -7,8 +7,13 @@ import org.ton.smartcontract.wallet.builder.TransferBuilder * Wallet contract we have a permission to perform operations on, such as transfers etc. */ interface TransferWallet : Wallet { + suspend fun beginTransfer(lite_api: LiteApi): TMB + /** * Perform a transfer of funds */ - suspend fun transfer(lite_api: LiteApi, builder: TMB.() -> Unit) + suspend fun transfer(lite_api: LiteApi, builder: TMB.() -> Unit) { + val msg = beginTransfer(lite_api).apply(builder).createMessage() + lite_api.sendMessage(msg) + } } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt index 568bc6c3..bf1a5ef7 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SeqnoTransferBuilder.kt @@ -6,7 +6,7 @@ import org.ton.cell.CellBuilder interface SeqnoTransferBuilder : TransferBuilder { var seqno: Int - override fun buildData(builder: CellBuilder.() -> Unit): Cell = super.buildData { + override fun createData(builder: CellBuilder.() -> Unit): Cell = super.createData { storeUInt(seqno, 32) apply(builder) } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt index ebf6ce76..21d76a9b 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedSeqnoTransferBuilder.kt @@ -4,8 +4,8 @@ import org.ton.cell.Cell import org.ton.cell.CellBuilder interface SignedSeqnoTransferBuilder : SignedTransferBuilder, SeqnoTransferBuilder { - override fun buildData(builder: CellBuilder.() -> Unit): Cell = - super.buildData { - super.buildData(builder) + override fun createData(builder: CellBuilder.() -> Unit): Cell = + super.createData { + super.createData(builder) } } diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt index ca915ac8..97f30c97 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/SignedTransferBuilder.kt @@ -6,9 +6,9 @@ import org.ton.cell.CellBuilder interface SignedTransferBuilder : TransferBuilder { fun signCell(data: Cell): ByteArray - override fun buildData(builder: CellBuilder.() -> Unit): Cell { + override fun createData(builder: CellBuilder.() -> Unit): Cell { val data = CellBuilder.createCell { apply(builder) } - return super.buildData { + return super.createData { storeBytes(signCell(data)) storeBits(data.bits) storeRefs(data.refs) diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt index fe4111d2..bcb8672a 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/builder/TransferBuilder.kt @@ -31,12 +31,12 @@ interface TransferBuilder { } } - fun buildData(builder: CellBuilder.() -> Unit = {}): Cell = CellBuilder.createCell { apply(builder) } + fun createData(builder: CellBuilder.() -> Unit = {}): Cell = CellBuilder.createCell { apply(builder) } - fun build(): Message = Message( + fun createMessage(): Message = Message( info = ExtInMsgInfo(src), init = null, - body = buildData { + body = createData { storeUInt(send_mode, 8) storeRef { val messageRelaxed = MessageRelaxed( diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt index 2b257410..3cfbb7c3 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R1.kt @@ -1,18 +1,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.BasicTransferWallet -class TransferWalletV1R1(private val private_key: PrivateKeyEd25519) : - BasicTransferWallet(private_key), - WalletV1R1 { - override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { - V1TransferBuilder( - private_key = private_key, - lite_api = lite_api, - src = address(), - seqno = seqno(lite_api) - ) - } -} +class TransferWalletV1R1(private_key: PrivateKeyEd25519, override val workchain_id: Int = 0) : + V1TransferWallet(private_key, workchain_id), WalletV1R1 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt index c93fcb9c..aedaaebc 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R2.kt @@ -1,18 +1,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.BasicTransferWallet -class TransferWalletV1R2(private val private_key: PrivateKeyEd25519) : - BasicTransferWallet(private_key), - WalletV1R2 { - override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { - V1TransferBuilder( - private_key = private_key, - lite_api = lite_api, - src = address(), - seqno = seqno(lite_api) - ) - } -} +class TransferWalletV1R2(private_key: PrivateKeyEd25519, override val workchain_id: Int = 0) : + V1TransferWallet(private_key, workchain_id), WalletV1R2 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt index 6da2d15e..eb32903b 100644 --- a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/TransferWalletV1R3.kt @@ -1,18 +1,6 @@ package org.ton.smartcontract.wallet.v1 import org.ton.api.pk.PrivateKeyEd25519 -import org.ton.lite.api.LiteApi -import org.ton.smartcontract.wallet.BasicTransferWallet -class TransferWalletV1R3(private val private_key: PrivateKeyEd25519) : - BasicTransferWallet(private_key), - WalletV1R3 { - override suspend fun transfer(lite_api: LiteApi, builder: V1TransferBuilder.() -> Unit) { - V1TransferBuilder( - private_key = private_key, - lite_api = lite_api, - src = address(), - seqno = seqno(lite_api) - ) - } -} +class TransferWalletV1R3(private_key: PrivateKeyEd25519, override val workchain_id: Int = 0) : + V1TransferWallet(private_key, workchain_id), WalletV1R3 diff --git a/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferWallet.kt b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferWallet.kt new file mode 100644 index 00000000..facafdec --- /dev/null +++ b/ton-smartcontract/src/commonMain/kotlin/org/ton/smartcontract/wallet/v1/V1TransferWallet.kt @@ -0,0 +1,16 @@ +package org.ton.smartcontract.wallet.v1 + +import org.ton.api.pk.PrivateKeyEd25519 +import org.ton.lite.api.LiteApi +import org.ton.smartcontract.wallet.BasicTransferWallet + +abstract class V1TransferWallet(private val private_key: PrivateKeyEd25519, override val workchain_id: Int) : + BasicTransferWallet(private_key) { + override suspend fun beginTransfer(lite_api: LiteApi): V1TransferBuilder = + V1TransferBuilder( + private_key = private_key, + lite_api = lite_api, + src = address(), + seqno = seqno(lite_api) + ) +} diff --git a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt index 221e3a8f..55b0f194 100644 --- a/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt +++ b/ton-smartcontract/src/jvmTest/kotlin/org/ton/smartcontract/wallet/v1/WalletV1R3Test.kt @@ -1,5 +1,6 @@ package org.ton.smartcontract.wallet.v1 +import kotlinx.coroutines.runBlocking import org.ton.api.pk.PrivateKeyEd25519 import org.ton.block.Coins import org.ton.block.Message @@ -122,12 +123,13 @@ class WalletV1R3Test { amount = Coins.of(1) seqno = 1 comment = text - }.build() + } @Test fun `test transfer message with 'Hello TON' comment`() { val wallet = wallet() - val message = wallet.exampleTransferMessage("Hello TON") + val message = + runBlocking { wallet.beginTransfer(liteClient()).exampleTransferMessage("Hello TON").createMessage() } val actual = CellBuilder.createCell { storeTlb(Message.tlbCodec(AnyTlbConstructor), message) } @@ -142,7 +144,8 @@ class WalletV1R3Test { @Test fun `test transfer BOC with 'Hello TON' comment`() { val wallet = wallet() - val message = wallet.exampleTransferMessage("Hello TON") + val message = + runBlocking { wallet.beginTransfer(liteClient()).exampleTransferMessage("Hello TON").createMessage() } val actual = BagOfCells(CellBuilder.createCell { storeTlb(Message.tlbCodec(AnyTlbConstructor), message)