Skip to content

Commit 19f423e

Browse files
authored
<feat>(contract): add payable contract wrapper feature. (#876)
1 parent 2cab838 commit 19f423e

File tree

3 files changed

+119
-9
lines changed

3 files changed

+119
-9
lines changed

src/main/java/org/fisco/bcos/sdk/v3/codec/datatypes/Function.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.fisco.bcos.sdk.v3.codec.datatypes;
22

3+
import java.math.BigInteger;
34
import java.util.Collections;
45
import java.util.List;
56
import org.fisco.bcos.sdk.v3.codec.Utils;
@@ -10,6 +11,7 @@ public class Function {
1011
private List<Type> inputParameters;
1112
private List<TypeReference<Type>> outputParameters;
1213
private int transactionAttribute = 0;
14+
private BigInteger value;
1315

1416
public Function(
1517
String name, List<Type> inputParameters, List<TypeReference<?>> outputParameters) {
@@ -30,6 +32,16 @@ public Function(
3032
this.transactionAttribute = transactionAttribute;
3133
}
3234

35+
public Function(
36+
String name,
37+
List<Type> inputParameters,
38+
List<TypeReference<?>> outputParameters,
39+
int transactionAttribute,
40+
BigInteger value) {
41+
this(name, inputParameters, outputParameters, transactionAttribute);
42+
this.value = value;
43+
}
44+
3345
public Function() {
3446
this.name = "";
3547
this.inputParameters = Collections.<Type>emptyList();
@@ -55,4 +67,12 @@ public int getTransactionAttribute() {
5567
public void setTransactionAttribute(int transactionAttribute) {
5668
this.transactionAttribute = transactionAttribute;
5769
}
70+
71+
public BigInteger getValue() {
72+
return value;
73+
}
74+
75+
public void setValue(BigInteger value) {
76+
this.value = value;
77+
}
5878
}

src/main/java/org/fisco/bcos/sdk/v3/codec/wrapper/ABIDefinition.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@
2929
public class ABIDefinition {
3030
private String name;
3131
private String type;
32-
private boolean constant;
33-
private boolean payable;
32+
private boolean constant = false;
33+
private boolean payable = false;
3434
private boolean anonymous;
3535
private String stateMutability;
3636
private List<ConflictField> conflictFields = new ArrayList<>();
3737

3838
private List<NamedType> inputs = new ArrayList<>();
3939
private List<NamedType> outputs = new ArrayList<>();
4040
private List<Long> selector = new ArrayList<>();
41-
public static List<String> CONSTANT_KEY = Arrays.asList("view");
41+
public static List<String> CONSTANT_KEY = Arrays.asList("view", "pure");
4242

4343
public ABIDefinition() {}
4444

@@ -213,7 +213,7 @@ public void setType(String type) {
213213
}
214214

215215
public boolean isPayable() {
216-
return this.payable;
216+
return this.payable || "payable".equals(getStateMutability());
217217
}
218218

219219
public void setPayable(boolean payable) {

src/main/java/org/fisco/bcos/sdk/v3/contract/Contract.java

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,52 @@ protected static <T extends Contract> T deploy(
272272
}
273273
}
274274

275+
protected static <T extends Contract> T deploy(
276+
Class<T> type,
277+
Client client,
278+
CryptoKeyPair credential,
279+
String binary,
280+
String abi,
281+
byte[] encodedConstructor,
282+
String path,
283+
BigInteger value)
284+
throws ContractException {
285+
try {
286+
Constructor<T> constructor =
287+
type.getDeclaredConstructor(String.class, Client.class, CryptoKeyPair.class);
288+
constructor.setAccessible(true);
289+
T contract = constructor.newInstance(null, client, credential);
290+
291+
ContractCodec codec = new ContractCodec(contract.cryptoSuite, client.isWASM());
292+
if (client.isWASM()) {
293+
// NOTE: it should set address first, contract.executeDeployTransaction will use it
294+
// as 'to'
295+
contract.setContractAddress(path);
296+
}
297+
TransactionReceipt transactionReceipt =
298+
contract.executeDeployTransaction(
299+
codec.encodeConstructorFromBytes(binary, encodedConstructor),
300+
abi,
301+
value);
302+
String contractAddress = transactionReceipt.getContractAddress();
303+
if (contractAddress == null
304+
|| transactionReceipt.getStatus()
305+
!= TransactionReceiptStatus.Success.getCode()) {
306+
// parse the receipt
307+
ReceiptParser.getErrorStatus(transactionReceipt);
308+
}
309+
contract.setContractAddress(client.isWASM() ? path : contractAddress);
310+
contract.setDeployReceipt(transactionReceipt);
311+
return contract;
312+
} catch (InstantiationException
313+
| InvocationTargetException
314+
| NoSuchMethodException
315+
| IllegalAccessException
316+
| ContractCodecException e) {
317+
throw new ContractException("deploy contract failed, error info: " + e.getMessage(), e);
318+
}
319+
}
320+
275321
private int generateTransactionAttribute(String funcName) {
276322
int attribute = 0;
277323
if (client.isWASM()) {
@@ -485,12 +531,33 @@ protected String asyncExecuteTransaction(
485531
this.contractAddress, data, this.credential, txAttribute, callback);
486532
}
487533

534+
protected String asyncExecuteTransaction(
535+
byte[] data,
536+
String funName,
537+
TransactionCallback callback,
538+
int dagAttribute,
539+
BigInteger value) {
540+
if (transactionManager != null) {
541+
try {
542+
return transactionManager.asyncSendTransaction(
543+
this.contractAddress, data, value, callback);
544+
} catch (JniException e) {
545+
logger.error("sendTransaction failed, error info: {}", e.getMessage(), e);
546+
return null;
547+
}
548+
}
549+
int txAttribute = generateTxAttributeWithDagFlag(funName, dagAttribute);
550+
return this.transactionProcessor.sendTransactionAsync(
551+
this.contractAddress, data, this.credential, txAttribute, callback);
552+
}
553+
488554
protected String asyncExecuteTransaction(Function function, TransactionCallback callback) {
489555
return this.asyncExecuteTransaction(
490556
this.functionEncoder.encode(function),
491557
function.getName(),
492558
callback,
493-
function.getTransactionAttribute());
559+
function.getTransactionAttribute(),
560+
function.getValue());
494561
}
495562

496563
protected TransactionReceipt executeTransaction(Function function) {
@@ -502,7 +569,7 @@ protected TransactionReceipt executeTransaction(Function function) {
502569
transactionManager.sendTransaction(
503570
this.contractAddress,
504571
this.functionEncoder.encode(function),
505-
BigInteger.ZERO);
572+
function.getValue());
506573
} catch (JniException e) {
507574
logger.error("sendTransaction failed, error info: {}", e.getMessage(), e);
508575
}
@@ -537,6 +604,25 @@ protected TransactionReceipt executeDeployTransaction(byte[] data, String abi) {
537604
this.contractAddress, data, abi, this.credential, txAttribute);
538605
}
539606

607+
protected TransactionReceipt executeDeployTransaction(
608+
byte[] data, String abi, BigInteger value) {
609+
if (transactionManager != null) {
610+
611+
TransactionReceipt transactionReceipt = null;
612+
try {
613+
transactionReceipt =
614+
this.transactionManager.sendTransaction(
615+
this.contractAddress, data, value, abi, true);
616+
} catch (JniException e) {
617+
logger.error("sendTransaction failed, error info: {}", e.getMessage(), e);
618+
}
619+
return transactionReceipt;
620+
}
621+
int txAttribute = generateTxAttributeWithDagFlag(Contract.FUNC_DEPLOY, 0);
622+
return this.transactionProcessor.deployAndGetReceipt(
623+
this.contractAddress, data, abi, this.credential, txAttribute);
624+
}
625+
540626
/** Adds a log field to {@link EventValues}. */
541627
public static class EventValuesWithLog {
542628
private final EventValues eventValues;
@@ -563,12 +649,16 @@ public TransactionReceipt.Logs getLog() {
563649
protected String createSignedTransaction(Function function) {
564650
if (transactionManager != null) {
565651
try {
652+
byte[] methodId =
653+
functionEncoder.buildMethodId(
654+
FunctionEncoderInterface.buildMethodSignature(
655+
function.getName(), function.getInputParameters()));
566656
return transactionManager.createSignedTransaction(
567657
this.contractAddress,
568658
this.functionEncoder.encode(function),
569-
BigInteger.ZERO,
570-
BigInteger.ZERO,
571-
BigInteger.ZERO,
659+
function.getValue(),
660+
transactionManager.getGasProvider().getGasPrice(methodId),
661+
transactionManager.getGasProvider().getGasLimit(methodId),
572662
client.getBlockLimit(),
573663
"",
574664
false);

0 commit comments

Comments
 (0)