Skip to content

Commit

Permalink
Add support for InvokeHostFunctionOperation & add Address class. (#481
Browse files Browse the repository at this point in the history
)
  • Loading branch information
overcat authored Jul 25, 2023
1 parent efa391f commit fef2d79
Show file tree
Hide file tree
Showing 391 changed files with 20,848 additions and 1,881 deletions.
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ java-stellar-sdk is licensed under an Apache-2.0 license. See the [LICENSE](http
## xdr to jave code generation
All the java source files in org.stellar.sdk.xdr package are generated using the `xdrgen` command from the [stellar/xdrgen](https://github.com/stellar/xdrgen)
```
xdrgen -o ./src/main/java/org/stellar/sdk/xdr -l java -n org.stellar.sdk.xdr ./xdr/Stellar-types.x ./xdr/Stellar-SCP.x ./xdr/Stellar-overlay.x ./xdr/Stellar-ledger-entries.x ./xdr/Stellar-ledger.x ./xdr/Stellar-transaction.x
xdrgen -o ./src/main/java/org/stellar/sdk/xdr -l java -n org.stellar.sdk.xdr ./xdr/*.x
```
170 changes: 170 additions & 0 deletions src/main/java/org/stellar/sdk/Address.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package org.stellar.sdk;

import com.google.common.base.Objects;
import org.stellar.sdk.xdr.Hash;
import org.stellar.sdk.xdr.SCAddress;
import org.stellar.sdk.xdr.SCVal;
import org.stellar.sdk.xdr.SCValType;

/**
* Represents a single address in the Stellar network. An address can represent an account or a
* contract.
*/
public class Address {

private final byte[] key;

private final AddressType type;

/**
* Creates a new {@link Address} from a Stellar public key or contract ID.
*
* @param address the StrKey encoded format of Stellar public key or contract ID.
*/
public Address(String address) {
if (StrKey.isValidStellarAccountId(address)) {
this.type = AddressType.ACCOUNT;
this.key = StrKey.decodeStellarAccountId(address);
} else if (StrKey.isValidContractId(address)) {
this.type = AddressType.CONTRACT;
this.key = StrKey.decodeContractId(address);
} else {
throw new IllegalArgumentException("Unsupported address type");
}
}

/**
* Creates a new {@link Address} from a Stellar public key.
*
* @param accountId the byte array of the Stellar public key.
* @return a new {@link Address} object from the given Stellar public key.
*/
public static Address fromAccount(byte[] accountId) {
return new Address(StrKey.encodeStellarAccountId(accountId));
}

/**
* Creates a new {@link Address} from a Stellar Contract ID.
*
* @param contractId the byte array of the Stellar Contract ID.
* @return a new {@link Address} object from the given Stellar Contract ID.
*/
public static Address fromContract(byte[] contractId) {
return new Address(StrKey.encodeContractId(contractId));
}

/**
* Creates a new {@link Address} from a {@link SCAddress} XDR object.
*
* @param scAddress the {@link SCAddress} object to convert
* @return a new {@link Address} object from the given XDR object
*/
public static Address fromSCAddress(SCAddress scAddress) {
switch (scAddress.getDiscriminant()) {
case SC_ADDRESS_TYPE_ACCOUNT:
return new Address(StrKey.encodeStellarAccountId(scAddress.getAccountId()));
case SC_ADDRESS_TYPE_CONTRACT:
return new Address(StrKey.encodeContractId(scAddress.getContractId().getHash()));
default:
throw new IllegalArgumentException("Unsupported address type");
}
}

/**
* Creates a new {@link Address} from a {@link SCVal} XDR object.
*
* @param scVal the {@link SCVal} object to convert
* @return a new {@link Address} object from the given XDR object
*/
public static Address fromSCVal(SCVal scVal) {
if (!SCValType.SCV_ADDRESS.equals(scVal.getDiscriminant())) {
throw new IllegalArgumentException("SCVal is not of type SCV_ADDRESS");
}
return Address.fromSCAddress(scVal.getAddress());
}

/**
* Converts this object to its {@link SCAddress} XDR object representation.
*
* @return a new {@link SCAddress} object from this object
*/
public SCAddress toSCAddress() {
SCAddress scAddress = new SCAddress();
switch (this.type) {
case ACCOUNT:
scAddress.setDiscriminant(org.stellar.sdk.xdr.SCAddressType.SC_ADDRESS_TYPE_ACCOUNT);
scAddress.setAccountId(KeyPair.fromPublicKey(this.key).getXdrAccountId());
break;
case CONTRACT:
scAddress.setDiscriminant(org.stellar.sdk.xdr.SCAddressType.SC_ADDRESS_TYPE_CONTRACT);
scAddress.setContractId(new Hash(this.key));
break;
default:
throw new IllegalArgumentException("Unsupported address type");
}
return scAddress;
}

/**
* Converts this object to its {@link SCVal} XDR object representation.
*
* @return a new {@link SCVal} object from this object
*/
public SCVal toSCVal() {
SCVal scVal = new SCVal();
scVal.setDiscriminant(SCValType.SCV_ADDRESS);
scVal.setAddress(this.toSCAddress());
return scVal;
}

/**
* Returns the byte array of the Stellar public key or contract ID.
*
* @return the byte array of the Stellar public key or contract ID.
*/
public byte[] getBytes() {
return key;
}

/**
* Returns the type of this address.
*
* @return the type of this address.
*/
public AddressType getType() {
return type;
}

@Override
public int hashCode() {
return Objects.hashCode(this.key, this.type);
}

@Override
public boolean equals(Object object) {
if (!(object instanceof Address)) {
return false;
}

Address other = (Address) object;
return Objects.equal(this.key, other.key) && Objects.equal(this.type, other.type);
}

@Override
public String toString() {
switch (this.type) {
case ACCOUNT:
return StrKey.encodeStellarAccountId(this.key);
case CONTRACT:
return StrKey.encodeContractId(this.key);
default:
throw new IllegalArgumentException("Unsupported address type");
}
}

/** Represents the type of the address. */
public enum AddressType {
ACCOUNT,
CONTRACT
}
}
62 changes: 62 additions & 0 deletions src/main/java/org/stellar/sdk/InvokeHostFunctionOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package org.stellar.sdk;

import java.util.Arrays;
import java.util.Collection;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.Singular;
import lombok.Value;
import lombok.experimental.SuperBuilder;
import org.stellar.sdk.xdr.HostFunction;
import org.stellar.sdk.xdr.InvokeHostFunctionOp;
import org.stellar.sdk.xdr.OperationType;
import org.stellar.sdk.xdr.SorobanAuthorizationEntry;

/**
* Represents <a
* href="https://developers.stellar.org/docs/fundamentals-and-concepts/list-of-operations#invoke-host-function"
* target="_blank">InvokeHostFunction</a> operation.
*
* @see <a href="https://developers.stellar.org/docs/fundamentals-and-concepts/list-of-operations"
* target="_blank">List of Operations</a>
*/
@EqualsAndHashCode(callSuper = true)
@SuperBuilder(toBuilder = true)
@Value
public class InvokeHostFunctionOperation extends Operation {

/** The host function to invoke. */
@NonNull HostFunction hostFunction;

/** The authorizations required to execute the host function */
@Singular("auth")
@NonNull
Collection<SorobanAuthorizationEntry> auth;

/**
* Constructs a new InvokeHostFunctionOperation object from the XDR representation of the {@link
* InvokeHostFunctionOperation}.
*
* @param op the XDR representation of the {@link InvokeHostFunctionOperation}.
*/
public static InvokeHostFunctionOperation fromXdr(InvokeHostFunctionOp op) {
return InvokeHostFunctionOperation.builder()
.hostFunction(op.getHostFunction())
.auth(Arrays.asList(op.getAuth()))
.build();
}

@Override
org.stellar.sdk.xdr.Operation.OperationBody toOperationBody(AccountConverter accountConverter) {
InvokeHostFunctionOp op = new InvokeHostFunctionOp();
op.setHostFunction(this.hostFunction);
op.setAuth(this.auth.toArray(new SorobanAuthorizationEntry[0]));

org.stellar.sdk.xdr.Operation.OperationBody body =
new org.stellar.sdk.xdr.Operation.OperationBody();
body.setDiscriminant(OperationType.INVOKE_HOST_FUNCTION);
body.setInvokeHostFunctionOp(op);

return body;
}
}
7 changes: 7 additions & 0 deletions src/main/java/org/stellar/sdk/KeyPair.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable;
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec;
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec;
import org.stellar.sdk.xdr.AccountID;
import org.stellar.sdk.xdr.DecoratedSignature;
import org.stellar.sdk.xdr.PublicKey;
import org.stellar.sdk.xdr.PublicKeyType;
Expand Down Expand Up @@ -200,6 +201,12 @@ public PublicKey getXdrPublicKey() {
return publicKey;
}

public AccountID getXdrAccountId() {
AccountID accountID = new AccountID();
accountID.setAccountID(getXdrPublicKey());
return accountID;
}

public SignerKey getXdrSignerKey() {
SignerKey signerKey = new SignerKey();
signerKey.setDiscriminant(SignerKeyType.SIGNER_KEY_TYPE_ED25519);
Expand Down
29 changes: 12 additions & 17 deletions src/main/java/org/stellar/sdk/Operation.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import org.stellar.sdk.xdr.*;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.SuperBuilder;
import org.stellar.sdk.xdr.XdrDataOutputStream;

/** Abstract class for operations. */
@SuperBuilder(toBuilder = true)
@EqualsAndHashCode
public abstract class Operation {
Operation() {}

private String mSourceAccount;
@Getter @Setter private String sourceAccount;

private static final BigDecimal ONE = new BigDecimal(10).pow(7);

Expand All @@ -31,7 +37,7 @@ protected static String fromXdrAmount(long value) {
public org.stellar.sdk.xdr.Operation toXdr(AccountConverter accountConverter) {
org.stellar.sdk.xdr.Operation xdr = new org.stellar.sdk.xdr.Operation();
if (getSourceAccount() != null) {
xdr.setSourceAccount(accountConverter.encode(mSourceAccount));
xdr.setSourceAccount(accountConverter.encode(sourceAccount));
}
xdr.setBody(toOperationBody(accountConverter));
return xdr;
Expand Down Expand Up @@ -200,6 +206,9 @@ public static Operation fromXdr(
case LIQUIDITY_POOL_WITHDRAW:
operation = new LiquidityPoolWithdrawOperation(body.getLiquidityPoolWithdrawOp());
break;
case INVOKE_HOST_FUNCTION:
operation = InvokeHostFunctionOperation.fromXdr(body.getInvokeHostFunctionOp());
break;
default:
throw new RuntimeException("Unknown operation body " + body.getDiscriminant());
}
Expand All @@ -218,20 +227,6 @@ public static Operation fromXdr(org.stellar.sdk.xdr.Operation xdr) {
return fromXdr(AccountConverter.enableMuxed(), xdr);
}

/** Returns operation source account. */
public String getSourceAccount() {
return mSourceAccount;
}

/**
* Sets operation source account.
*
* @param sourceAccount
*/
void setSourceAccount(String sourceAccount) {
mSourceAccount = checkNotNull(sourceAccount, "sourceAccount cannot be null");
}

/**
* Generates OperationBody XDR object
*
Expand Down
Loading

0 comments on commit fef2d79

Please sign in to comment.