1: <?php declare( strict_types = 1 );
2:
3: namespace Waves\Transactions;
4:
5: use Exception;
6: use Waves\Account\PrivateKey;
7: use Waves\Common\Base58String;
8: use Waves\Account\PublicKey;
9: use Waves\Common\Base64String;
10: use Waves\Common\ExceptionCode;
11: use Waves\Common\Json;
12: use Waves\Model\ChainId;
13:
14: use Waves\Transactions\SetScriptTransaction as CurrentTransaction;
15:
16: class SetScriptTransaction extends Transaction
17: {
18: const TYPE = 13;
19: const LATEST_VERSION = 2;
20: const MIN_FEE = 100_000;
21:
22: private Base64String $script;
23:
24: static function build( PublicKey $sender, Base64String $script ): CurrentTransaction
25: {
26: $tx = new CurrentTransaction;
27: $tx->setBase( $sender, CurrentTransaction::TYPE, CurrentTransaction::LATEST_VERSION, CurrentTransaction::MIN_FEE );
28:
29: // SET_SCRIPT TRANSACTION
30: {
31: $tx->setScript( $script );
32: }
33:
34: // ADDITIONAL FEE CALCULATION
35: $tx->setFee( Amount::of( CurrentTransaction::calculateFee( strlen( $tx->bodyBytes() ) ) ) );
36:
37: return $tx;
38: }
39:
40: static function calculateFee( int $bodyBytesLen ): int
41: {
42: return 100_000 * ( 1 + intdiv( $bodyBytesLen - 1, 1024 ) );
43: }
44:
45: function getUnsigned(): CurrentTransaction
46: {
47: // VERSION
48: if( $this->version() !== CurrentTransaction::LATEST_VERSION )
49: throw new Exception( __FUNCTION__ . ' unexpected version = ' . $this->version(), ExceptionCode::UNEXPECTED );
50:
51: // BASE
52: $pb_Transaction = $this->getProtobufTransactionBase();
53:
54: // SET_SCRIPT TRANSACTION
55: {
56: $pb_TransactionData = new \Waves\Protobuf\SetScriptTransactionData;
57: // SCRIPT
58: {
59: $pb_TransactionData->setScript( $this->script()->bytes() );
60: }
61: }
62:
63: // SET_SCRIPT TRANSACTION
64: $this->setBodyBytes( $pb_Transaction->setSetScript( $pb_TransactionData )->serializeToString() );
65: return $this;
66: }
67:
68: function script(): Base64String
69: {
70: if( !isset( $this->script ) )
71: $this->script = $this->json->exists( 'script' ) ? $this->json->get( 'script' )->asBase64String() : Base64String::emptyString();
72: return $this->script;
73: }
74:
75: function setScript( Base64String $script = null ): CurrentTransaction
76: {
77: $script = $script ?? Base64String::emptyString();
78: $this->script = $script;
79: $this->json->put( 'script', $script->toJsonValue() );
80: return $this;
81: }
82:
83: // COMMON
84:
85: function __construct( Json $json = null )
86: {
87: parent::__construct( $json );
88: }
89:
90: function addProof( PrivateKey $privateKey, int $index = null ): CurrentTransaction
91: {
92: $proof = (new \deemru\WavesKit)->sign( $this->bodyBytes(), $privateKey->bytes() );
93: if( $proof === false )
94: throw new Exception( __FUNCTION__ . ' unexpected sign() error', ExceptionCode::UNEXPECTED );
95: $proof = Base58String::fromBytes( $proof )->encoded();
96:
97: $proofs = $this->proofs();
98: if( !isset( $index ) )
99: $proofs[] = $proof;
100: else
101: $proofs[$index] = $proof;
102: return $this->setProofs( $proofs );
103: }
104:
105: /**
106: * @return CurrentTransaction
107: */
108: function setType( int $type )
109: {
110: parent::setType( $type );
111: return $this;
112: }
113:
114: /**
115: * @return CurrentTransaction
116: */
117: function setSender( PublicKey $sender )
118: {
119: parent::setSender( $sender );
120: return $this;
121: }
122:
123: /**
124: * @return CurrentTransaction
125: */
126: function setVersion( int $version )
127: {
128: parent::setVersion( $version );
129: return $this;
130: }
131:
132: /**
133: * @return CurrentTransaction
134: */
135: function setFee( Amount $fee )
136: {
137: parent::setFee( $fee );
138: return $this;
139: }
140:
141: /**
142: * @return CurrentTransaction
143: */
144: function setChainId( ChainId $chainId = null )
145: {
146: parent::setChainId( $chainId );
147: return $this;
148: }
149:
150: /**
151: * @return CurrentTransaction
152: */
153: function setTimestamp( int $timestamp = null )
154: {
155: parent::setTimestamp( $timestamp );
156: return $this;
157: }
158:
159: /**
160: * @param array<int, string> $proofs
161: * @return CurrentTransaction
162: */
163: function setProofs( array $proofs = null )
164: {
165: parent::setProofs( $proofs );
166: return $this;
167: }
168:
169: function bodyBytes(): string
170: {
171: if( !isset( $this->bodyBytes ) )
172: $this->getUnsigned();
173: return parent::bodyBytes();
174: }
175: }
176: