github.com/algorand/go-algorand-sdk@v1.24.0/templates/limitOrder.go (about) 1 package templates 2 3 import ( 4 "encoding/base64" 5 6 "github.com/algorand/go-algorand-sdk/crypto" 7 "github.com/algorand/go-algorand-sdk/future" 8 "github.com/algorand/go-algorand-sdk/types" 9 ) 10 11 // LimitOrder represents a swap between Algos and an Asset at some ratio or better. 12 // 13 // Deprecated: Use TealCompile source compilation instead. 14 type LimitOrder struct { 15 ContractTemplate 16 assetID uint64 17 owner string 18 } 19 20 // GetSwapAssetsTransaction returns a group transaction array which transfer funds according to the contract's ratio 21 // assetAmount: amount of assets to be sent 22 // contract: byteform of the contract from the payer 23 // secretKey: secret key for signing transactions 24 // microAlgoAmount: number of microAlgos to transfer 25 // params: txn params for the transactions 26 // the first payment sends money (Algos) from contract to the recipient (we'll call him Buyer), closing the rest of the account to Owner 27 // the second payment sends money (the asset) from Buyer to the Owner 28 // these transactions will be rejected if they do not meet the restrictions set by the contract 29 // 30 // Deprecated: Use TealCompile source compilation instead. 31 func (lo LimitOrder) GetSwapAssetsTransaction(assetAmount uint64, microAlgoAmount uint64, contract, secretKey []byte, params types.SuggestedParams) ([]byte, error) { 32 var buyerAddress types.Address 33 copy(buyerAddress[:], secretKey[32:]) 34 contractAddress := crypto.AddressFromProgram(contract) 35 algosForAssets, err := future.MakePaymentTxn(contractAddress.String(), buyerAddress.String(), microAlgoAmount, nil, "", params) 36 if err != nil { 37 return nil, err 38 } 39 assetsForAlgos, err := future.MakeAssetTransferTxn(buyerAddress.String(), lo.owner, assetAmount, nil, params, "", lo.assetID) 40 if err != nil { 41 return nil, err 42 } 43 44 gid, err := crypto.ComputeGroupID([]types.Transaction{algosForAssets, assetsForAlgos}) 45 if err != nil { 46 return nil, err 47 } 48 algosForAssets.Group = gid 49 assetsForAlgos.Group = gid 50 51 logicSig, err := crypto.MakeLogicSig(contract, nil, nil, crypto.MultisigAccount{}) 52 if err != nil { 53 return nil, err 54 } 55 _, algosForAssetsSigned, err := crypto.SignLogicsigTransaction(logicSig, algosForAssets) 56 if err != nil { 57 return nil, err 58 } 59 _, assetsForAlgosSigned, err := crypto.SignTransaction(secretKey, assetsForAlgos) 60 if err != nil { 61 return nil, err 62 } 63 64 var signedGroup []byte 65 signedGroup = append(signedGroup, algosForAssetsSigned...) 66 signedGroup = append(signedGroup, assetsForAlgosSigned...) 67 68 return signedGroup, nil 69 } 70 71 // MakeLimitOrder allows a user to exchange some number of assets for some number of algos. 72 // Fund the contract with some number of Algos to limit the maximum number of 73 // Algos you're willing to trade for some other asset. 74 // 75 // Works on two cases: 76 // * trading Algos for some other asset 77 // * closing out Algos back to the originator after a timeout 78 // 79 // trade case, a 2 transaction group: 80 // gtxn[0] (this txn) Algos from Me to Other 81 // gtxn[1] asset from Other to Me 82 // 83 // We want to get _at least_ some amount of the other asset per our Algos 84 // gtxn[1].AssetAmount / gtxn[0].Amount >= N / D 85 // === 86 // gtxn[1].AssetAmount * D >= gtxn[0].Amount * N 87 // 88 // close-out case: 89 // txn alone, close out value after timeout 90 // 91 // Parameters: 92 // - owner: the address to refund funds to on timeout 93 // - assetID: ID of the transferred asset 94 // - ratn: exchange rate (N asset per D Algos, or better) 95 // - ratd: exchange rate (N asset per D Algos, or better) 96 // - expiryRound: the round at which the account expires 97 // - minTrade: the minimum amount (of Algos) to be traded away 98 // - maxFee: maximum fee used by the limit order transaction 99 // 100 // Deprecated: Use TealCompile source compilation instead. 101 func MakeLimitOrder(owner string, assetID, ratn, ratd, expiryRound, minTrade, maxFee uint64) (LimitOrder, error) { 102 const referenceProgram = "ASAKAAEFAgYEBwgJCiYBIP68oLsUSlpOp7Q4pGgayA5soQW8tgf8VlMlyVaV9qITMRYiEjEQIxIQMQEkDhAyBCMSQABVMgQlEjEIIQQNEDEJMgMSEDMBECEFEhAzAREhBhIQMwEUKBIQMwETMgMSEDMBEiEHHTUCNQExCCEIHTUENQM0ATQDDUAAJDQBNAMSNAI0BA8QQAAWADEJKBIxAiEJDRAxBzIDEhAxCCISEBA=" 103 referenceAsBytes, err := base64.StdEncoding.DecodeString(referenceProgram) 104 if err != nil { 105 return LimitOrder{}, err 106 } 107 108 var referenceOffsets = []uint64{ /*maxFee*/ 5 /*minTrade*/, 7 /*assetID*/, 9 /*ratd*/, 10 /*ratn*/, 11 /*expiryRound*/, 12 /*ownerAddr*/, 16} 109 ownerAddr, err := types.DecodeAddress(owner) 110 if err != nil { 111 return LimitOrder{}, err 112 } 113 injectionVector := []interface{}{maxFee, minTrade, assetID, ratd, ratn, expiryRound, ownerAddr} 114 injectedBytes, err := inject(referenceAsBytes, referenceOffsets, injectionVector) 115 if err != nil { 116 return LimitOrder{}, err 117 } 118 119 address := crypto.AddressFromProgram(injectedBytes) 120 lo := LimitOrder{ 121 ContractTemplate: ContractTemplate{ 122 address: address.String(), 123 program: injectedBytes, 124 }, 125 owner: owner, 126 assetID: assetID, 127 } 128 return lo, err 129 }