Skip to content

Commit

Permalink
Merge branch 'master' into support-solana-tx-with-external-signatures
Browse files Browse the repository at this point in the history
  • Loading branch information
satoshiotomakan authored Jan 3, 2025
2 parents ddf53ed + a6e7ac0 commit c5e16aa
Show file tree
Hide file tree
Showing 81 changed files with 3,488 additions and 185 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,31 @@ class TestEthereumAbiDecoder {
assertEquals(decodingOutput.getTokens(0).name, "name")
assertEquals(decodingOutput.getTokens(0).stringValue, "deadbeef")
}

@Test
fun testEthereumAbiGetFunctionSignature() {
val abiJson = """
{
"constant": false,
"inputs": [
{
"name": "_to",
"type": "address"
},
{
"name": "_value",
"type": "uint256"
}
],
"name": "transfer",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
}
""".trimIndent()

val functionSignature = wallet.core.jni.EthereumAbi.getFunctionSignature(abiJson)
assertEquals(functionSignature, "transfer(address,uint256)")
}
}
15 changes: 15 additions & 0 deletions codegen-v2/manifest/TWEthereumAbi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,18 @@ functions:
is_constant: true
is_nullable: false
is_pointer: true
- name: TWEthereumAbiGetFunctionSignature
is_public: true
is_static: true
params:
- name: abi
type:
variant: string
is_constant: true
is_nullable: false
is_pointer: true
return_type:
variant: string
is_constant: true
is_nullable: true
is_pointer: true
25 changes: 12 additions & 13 deletions codegen/lib/kotlin_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ def self.js_parameters(params)
def self.calling_parameters_ios(params)
names = params.map do |param|
name = fix_name(param.name)
if param.type.name == :data
"#{name}Data#{convert_calling_type_ios(param.type)}"
elsif param.type.name == :string
"#{name}String#{convert_calling_type_ios(param.type)}"
else
"#{name}#{convert_calling_type_ios(param.type)}"
end
end
names.join(', ')
end
Expand All @@ -56,7 +62,7 @@ def self.fix_name(name)
when ''
"value"
when 'val'
"value"
"value"
when 'return'
'`return`'
else
Expand All @@ -65,19 +71,12 @@ def self.fix_name(name)
end

def self.convert_calling_type_ios(t)
case t.name
when :data
"#{if t.is_nullable then '?' else '' end}.toTwData()"
when :string
"#{if t.is_nullable then '?' else '' end}.toTwString()"
if t.is_enum
"#{if t.is_nullable then '?' else '' end}.nativeValue"
elsif t.is_class
"#{if t.is_nullable then '?' else '' end}.pointer"
else
if t.is_enum
"#{if t.is_nullable then '?' else '' end}.nativeValue"
elsif t.is_class
"#{if t.is_nullable then '?' else '' end}.pointer"
else
''
end
''
end
end

Expand Down
30 changes: 3 additions & 27 deletions codegen/lib/templates/java/class.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import java.security.InvalidParameterException;
import java.util.HashSet;
import wallet.core.java.GenericPhantomReference;

<% less = entity.static_methods.detect{ |i| i.name == 'Less' } -%>
<% equal = entity.static_methods.detect{ |i| i.name == 'Equal' } -%>
Expand All @@ -21,7 +21,7 @@ public final class <%= entity.name %> {
<%= entity.name %> instance = new <%= entity.name %>();
instance.nativeHandle = nativeHandle;
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
<%= entity.name %>PhantomReference.register(instance, nativeHandle);
GenericPhantomReference.register(instance, nativeHandle, <%= entity.name %>::nativeDelete);
<% end -%>
return instance;
}
Expand Down Expand Up @@ -96,32 +96,8 @@ public final class <%= entity.name %> {
throw new InvalidParameterException();
}

<%= entity.name %>PhantomReference.register(this, nativeHandle);
GenericPhantomReference.register(this, nativeHandle, <%= entity.name %>::nativeDelete);
}

<%- end -%>
}
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
class <%= entity.name %>PhantomReference extends java.lang.ref.PhantomReference<<%= entity.name %>> {
private static java.util.Set<<%= entity.name %>PhantomReference> references = new HashSet<<%= entity.name %>PhantomReference>();
private static java.lang.ref.ReferenceQueue<<%= entity.name %>> queue = new java.lang.ref.ReferenceQueue<<%= entity.name %>>();
private long nativeHandle;

private <%= entity.name %>PhantomReference(<%= entity.name %> referent, long nativeHandle) {
super(referent, queue);
this.nativeHandle = nativeHandle;
}

static void register(<%= entity.name %> referent, long nativeHandle) {
references.add(new <%= entity.name %>PhantomReference(referent, nativeHandle));
}

public static void doDeletes() {
<%= entity.name %>PhantomReference ref = (<%= entity.name %>PhantomReference) queue.poll();
for (; ref != null; ref = (<%= entity.name %>PhantomReference) queue.poll()) {
<%= entity.name %>.nativeDelete(ref.nativeHandle);
references.remove(ref);
}
}
}
<% end -%>
9 changes: 9 additions & 0 deletions codegen/lib/templates/kotlin/android_class.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ actual class <%= entity.name %> private constructor(

init {
if (nativeHandle == 0L) throw IllegalArgumentException()
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
GenericPhantomReference.register(this, nativeHandle, ::delete)
<% end -%>
}
<%# Constructors -%>
<%- constructors.each do |constructor| -%>
Expand Down Expand Up @@ -52,6 +55,12 @@ actual class <%= entity.name %> private constructor(
@JvmStatic
@JvmName("createFromNative")
private fun createFromNative(nativeHandle: Long) = <%= entity.name %>(nativeHandle)

<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
@JvmStatic
@JvmName("delete")
private external fun delete(handle: Long)
<%- end -%>
<%- constructors.each do |constructor| -%>

@JvmStatic
Expand Down
56 changes: 45 additions & 11 deletions codegen/lib/templates/kotlin/ios_class.erb
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@

import cnames.structs.TW<%= entity.name %>
import kotlinx.cinterop.CPointer
import kotlinx.cinterop.toCValues

<% constructors = entity.static_methods.select { |method| method.name.start_with?('Create') } -%>
<% methods = entity.methods.select { |method| not method.name.start_with?('Delete') } -%>
<% static_methods = entity.static_methods.select { |method| not method.name.start_with?('Create') } -%>
actual class <%= entity.name %> constructor(
val pointer: CPointer<TW<%= entity.name %>>,
) {
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
@OptIn(ExperimentalStdlibApi::class)
private val cleaner = kotlin.native.internal.createCleaner(pointer) { ptr ->
TW<%= entity.name %>Delete(ptr)
}
<% end -%>
<%# Constructors -%>
<%- constructors.each do |constructor| -%>

<% if constructor.return_type.is_nullable -%>
@Throws(IllegalArgumentException::class)
actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this(
TW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.calling_parameters_ios(constructor.parameters) %>) ?: throw IllegalArgumentException()
<% else -%>
actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this(
TW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.calling_parameters_ios(constructor.parameters) %>)!!
<% end -%>
actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this(
wrapperTW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.arguments(constructor.parameters) %>)
)
<% end -%>
<%# Property declarations -%>
Expand All @@ -31,12 +35,38 @@ actual class <%= entity.name %> constructor(
<%# Method declarations -%>
<% methods.each do |method| -%>

actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters.drop(1)) %>)<%= KotlinHelper.return_type(method.return_type) %> =
<%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(pointer#{', ' if not method.parameters.one?}#{KotlinHelper.calling_parameters_ios(method.parameters.drop(1))})") %>
actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters.drop(1)) %>)<%= KotlinHelper.return_type(method.return_type) %> {
<%= render('kotlin/ios_parameter_access.erb', { method: method }) -%>
val result = <%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(pointer#{', ' if not method.parameters.one?}#{KotlinHelper.calling_parameters_ios(method.parameters.drop(1))})") %>
<%= render('kotlin/ios_parameter_release.erb', { method: method }) -%>
return result
}
<% end -%>
<% if entity.static_properties.any? || static_methods.any? -%>
<% if entity.static_properties.any? || static_methods.any? || constructors.any? -%>

<%= if entity.static_properties.any? || static_methods.any? then "actual" else "private" end %> companion object {
<%# Constructor wrappers -%>
<% if constructors.any? -%>
<% constructors.each do |constructor| -%>

actual companion object {
<% if constructor.return_type.is_nullable -%>
@Throws(IllegalArgumentException::class)
<% end -%>
private fun wrapperTW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.parameters(constructor.parameters) %>): CPointer<TW<%= entity.name %>> {
<%= render('kotlin/ios_parameter_access.erb', { method: constructor, more_index: 4 }) -%>
val result = TW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.calling_parameters_ios(constructor.parameters) %>)
<%= render('kotlin/ios_parameter_release.erb', { method: constructor, more_index: 4 }) -%>
<% if constructor.return_type.is_nullable -%>
if (result == null) {
throw IllegalArgumentException()
}
return result
<% else -%>
return result!!
<% end -%>
}
<% end -%>
<% end -%>
<%# Static property declarations -%>
<% entity.static_properties.each do |property| -%>

Expand All @@ -46,8 +76,12 @@ actual class <%= entity.name %> constructor(
<%# Static method declarations -%>
<% static_methods.each do |method| -%>

actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters) %>)<%= KotlinHelper.return_type(method.return_type) %> =
<%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(#{KotlinHelper.calling_parameters_ios(method.parameters)})") %>
actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters) %>)<%= KotlinHelper.return_type(method.return_type) %> {
<%= render('kotlin/ios_parameter_access.erb', { method: method, more_index: 4 }) -%>
val result = <%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(#{KotlinHelper.calling_parameters_ios(method.parameters)})") %>
<%= render('kotlin/ios_parameter_release.erb', { method: method, more_index: 4 }) -%>
return result
}
<% end -%>
}
<% end -%>
Expand Down
8 changes: 6 additions & 2 deletions codegen/lib/templates/kotlin/ios_enum.erb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ actual enum class <%= entity.name %>(
<%- entity.methods.each do |method| -%>
<%- next if method.name.start_with?('Delete') -%>

actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters.drop(1)) %>)<%= KotlinHelper.return_type(method.return_type) %> =
TW<%= entity.name %><%= method.name %>(value<%= ', ' if not method.parameters.one? %><%= KotlinHelper.calling_parameters_ios(method.parameters.drop(1)) %>)<%= KotlinHelper.convert_calling_return_type_ios(method.return_type) %>
actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters.drop(1)) %>)<%= KotlinHelper.return_type(method.return_type) %> {
<%= render('kotlin/ios_parameter_access.erb', { method: method }) -%>
val result = TW<%= entity.name %><%= method.name %>(value<%= ', ' if not method.parameters.one? %><%= KotlinHelper.calling_parameters_ios(method.parameters.drop(1)) %>)<%= KotlinHelper.convert_calling_return_type_ios(method.return_type) %>
<%= render('kotlin/ios_parameter_release.erb', { method: method }) -%>
return result
}
<%- end -%>
<%# Value -%>
<% if entity.cases.any? { |e| !e.value.nil? } -%>
Expand Down
27 changes: 27 additions & 0 deletions codegen/lib/templates/kotlin/ios_parameter_access.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<%
method = locals[:method]
more_index = locals[:more_index] || 0

method.parameters.each do |param| -%>
<% if param.type.name == :data -%>
<% if param.type.is_nullable -%>
<%= ' ' * more_index %> val <%= KotlinHelper.fix_name(param.name) %>Data = if (<%= KotlinHelper.fix_name(param.name) %> == null) {
<%= ' ' * more_index %> null
<%= ' ' * more_index %> } else {
<%= ' ' * more_index %> TWDataCreateWithBytes(<%= KotlinHelper.fix_name(param.name) %>.toUByteArray().toCValues(), <%= KotlinHelper.fix_name(param.name) %>.size.toULong())
<%= ' ' * more_index %> }
<% else -%>
<%= ' ' * more_index %> val <%= KotlinHelper.fix_name(param.name) %>Data = TWDataCreateWithBytes(<%= KotlinHelper.fix_name(param.name) %>.toUByteArray().toCValues(), <%= KotlinHelper.fix_name(param.name) %>.size.toULong())
<% end -%>
<% elsif param.type.name == :string -%>
<% if param.type.is_nullable -%>
<%= ' ' * more_index %> val <%= KotlinHelper.fix_name(param.name) %>String = if (<%= KotlinHelper.fix_name(param.name) %> == null) {
<%= ' ' * more_index %> null
<%= ' ' * more_index %> } else {
<%= ' ' * more_index %> TWStringCreateWithUTF8Bytes(<%= KotlinHelper.fix_name(param.name) %>)
<%= ' ' * more_index %> }
<% else -%>
<%= ' ' * more_index %> val <%= KotlinHelper.fix_name(param.name) %>String = TWStringCreateWithUTF8Bytes(<%= KotlinHelper.fix_name(param.name) %>)
<% end -%>
<% end -%>
<% end -%>
23 changes: 23 additions & 0 deletions codegen/lib/templates/kotlin/ios_parameter_release.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<%
method = locals[:method]
more_index = locals[:more_index] || 0

method.parameters.each do |param| -%>
<% if param.type.name == :data -%>
<% if param.type.is_nullable -%>
<%= ' ' * more_index %> if (<%= KotlinHelper.fix_name(param.name) %>Data != null) {
<%= ' ' * more_index %> TWDataDelete(<%= KotlinHelper.fix_name(param.name) %>Data)
<%= ' ' * more_index %> }
<% else -%>
<%= ' ' * more_index %> TWDataDelete(<%= KotlinHelper.fix_name(param.name) %>Data)
<% end -%>
<% elsif param.type.name == :string -%>
<% if param.type.is_nullable -%>
<%= ' ' * more_index %> if (<%= KotlinHelper.fix_name(param.name) %>String != null) {
<%= ' ' * more_index %> TWStringDelete(<%= KotlinHelper.fix_name(param.name) %>String)
<%= ' ' * more_index %> }
<% else -%>
<%= ' ' * more_index %> TWStringDelete(<%= KotlinHelper.fix_name(param.name) %>String)
<% end -%>
<% end -%>
<% end -%>
10 changes: 8 additions & 2 deletions codegen/lib/templates/kotlin/ios_struct.erb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<%= render('kotlin/package.erb') %>

import kotlinx.cinterop.toCValues

actual object <%= entity.name %> {
<%# Static property declarations -%>
<% entity.static_properties.each do |property| -%>
Expand All @@ -10,7 +12,11 @@ actual object <%= entity.name %> {
<% entity.static_methods.each do |method| -%>
<% next if method.name.start_with?('Create') -%>

actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters) %>)<%= KotlinHelper.return_type(method.return_type) %> =
<%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(#{KotlinHelper.calling_parameters_ios(method.parameters)})") %>
actual fun <%= KotlinHelper.format_name(method.name) %>(<%= KotlinHelper.parameters(method.parameters) %>)<%= KotlinHelper.return_type(method.return_type) %> {
<%= render('kotlin/ios_parameter_access.erb', { method: method }) -%>
val result = <%= KotlinHelper.convert_calling_return_type_ios(method.return_type, "TW#{entity.name}#{method.name}(#{KotlinHelper.calling_parameters_ios(method.parameters)})") %>
<%= render('kotlin/ios_parameter_release.erb', { method: method }) -%>
return result
}
<% end -%>
}
3 changes: 3 additions & 0 deletions codegen/lib/templates/kotlin/js_accessors_class.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ external interface Js<%= entity.name %> {
<%- entity.properties.each do |property| -%>
fun <%= KotlinHelper.fix_name(WasmCppHelper.format_name(property.name)) %>()<%= KotlinHelper.js_return_type(property.return_type) %>
<%- end -%>
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
fun delete()
<% end -%>
<% entity.methods.each do |method| -%>
<% next if method.name == "Delete" -%>
fun <%= KotlinHelper.fix_name(WasmCppHelper.format_name(method.name)) %>(<%= KotlinHelper.js_parameters(method.parameters.drop(1)) %>)<%= KotlinHelper.js_return_type(method.return_type) %>
Expand Down
15 changes: 15 additions & 0 deletions codegen/lib/templates/kotlin/js_class.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@
actual class <%= entity.name %> constructor(
val jsValue: Js<%= entity.name %>,
) {
<% unless entity.methods.select{ |x| x.name == "Delete" }.empty? -%>
private val finalizationRegistry =
js(
"""
new FinalizationRegistry(function(heldValue) {
heldValue.delete();
})
"""
)

init {
finalizationRegistry.register(this, jsValue)
}
<% end -%>

<%# Constructors -%>
<%- constructors.each do |constructor| -%>

Expand Down
7 changes: 7 additions & 0 deletions include/TrustWalletCore/TWEthereumAbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,11 @@ TWString* _Nullable TWEthereumAbiDecodeCall(TWData* _Nonnull data, TWString* _No
TW_EXPORT_STATIC_METHOD
TWData* _Nonnull TWEthereumAbiEncodeTyped(TWString* _Nonnull messageJson);

/// Get function signature from Ethereum ABI json
///
/// \param abi The function ABI json string, for example: {"inputs":[{"internalType":"bool","name":"arg1","type":"bool"}],"name":"fun1","outputs":[],"stateMutability":"nonpayable","type":"function"}
/// \return the function type signature, of the form "baz(int32,uint256)", null if the abi is invalid.
TW_EXPORT_STATIC_METHOD
TWString* _Nullable TWEthereumAbiGetFunctionSignature(TWString* _Nonnull abi);

TW_EXTERN_C_END
Loading

0 comments on commit c5e16aa

Please sign in to comment.